win32线程退出C语言,多线程在C、Win32和MFC下的使用方法

下载源代码

一.前言

线程是执行路径。一个进程至少要有一个线程,也可能包含多个线程。若进程关闭了,则在进程中所有的线程也自动被销毁。当我们在一个应用程序中创建一个线程时,实际上,它是第二个线程。在C或C++中,程序的入口函数是main或wmain(Unicode版本)。在windows的运用程序中,程序的入口点是WinMain或wWinMain。当程序启动时,操作系统创建第一个线程。因此,windows是一个多任务操作系统。

二.线程函数

线程函数跟普通函数一样,它带有一个long

void的指针参数。我们可以传任何类型的数据给这个void类型的指针数据。一个简单的线程函数如下:ThreadFunction(LPVOID param)

{

//do something

……

……

//return value;

}

三.线程属性

线程的优先级控制进程中线程的优先级。线程属性如下:

最高:THREAD_PRIORITY_HIGHEST

● 高于标准:THREAD_PRIORITY_ABOVE_NORMAL

标准:THREAD_PRIORITY_NORMAL

● 低于标准:THREAD_PRIORITY_BELOW_NORMAL

空闲:THREAD_PRIORITY_IDEL

我们可以用CreateThread函数设置线程优先级。在Win32

API函数中,我们用GetThreadPriority 和

SetThreadPriority获取和设置线程优先级;或者我们也可以用CWinThread的函数,在代码中,我们可以自由的调用它。优先级函数返回一个BOOL类型的变量。

四.各个平台下的多线程

1.C运行时库的多线程

_beginthread

● _beginthreadex

● _endthread

_endthreadex

以上C运行时库的函数都包含在头文件process.h中。要确保在Microsoft Visual

Studio的工程设置是multithreaded

DLL。在C运行时库中,通常是用_beginthread和_beginthreadex函数来创建线程。但是,这些线程有些不同。_beginthreadex有一些附加的参数,比如安全性和线程地址。我们用_beginthread来创建线程的话,要用_endthread来结束线程。_endthread将自动关闭线程的句柄。但是,若我们用_endthreadex的话,要用Win32

API的函数CloseHandle来关闭线程句柄。C运行时库包含了线程本地存储区(TLS)。我们可以用API或特定的编译代码去使用线程本地存储区。TlsAlloc,TlsFree,TlsGetValue和TlsSetValue通常用来储存指定的线程数据。Microsoft建议,假如你用了C运行时库的_beginthread函数,你就不要使用像ExitThread或者CreateThread这样的Win32

API函数。因为,假如你那样使用的话,可能会导致死锁。_beginthread在创建线程的时候使用多个参数。我们的例子是基于一个简单控制台的程序。用户键入线程数目创建线程,然后我们执行每一个线程。// Secound Thread function

void ThreadProc(void *param);

// First thread

int main()

{

int n;

int i;

int val = 0;

HANDLE handle;

printf("\t Thread Demo\n");

printf("Enter the number of threads : ");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

val = i;

handle = (HANDLE) _beginthread( ThreadProc,0,&val); // create thread

WaitForSingleObject(handle,INFINITE);

}

return 0;

}

void ThreadProc(void *param)

{

int h=*((int*)param);

printf("%d Thread is Running!\n",h);

_endthread();

}

主线程用Win32 API的函数WaitForSingleObject来等待另一个线程的完成。

2.MFC的多线程

CWinThread是所有线程操作的基类。MFC支持两种类型的线程:用户界面线程和工作线程。用户界面线程是基于windows消息。工作进程运行在后台进程中。CWinThread支持工作线程和用户界面线程。但是,这里只讨论工作线程。

MFC的类层次结构

CObject

CCmdTarget

CWinThread

CWinApp

在以上的类层次结构中,CWinApp应用程序类继承自CWinThread。因此假如我们创建了一个应用程序类,也同样创建了线程。假如我们创建线程的话,它是次线程。母类CObject有一些功能像是:支持系列化、运行时间类消息、支持调试。派生类CWinThread有同样的功能。经常用到的一些数据成员和成员函数如下:

数据成员:

● m_hThread – 当前线程句柄

● m_bAutoDelete – 设置线程是否自动释放

m_nThreadID – 当前线程的ID

函数成员:

● CreateThread – 启动线程的exec执行

● SuspendThread – 挂起线程,

增加线程挂起数。

● ResumeThread – 恢复线程,减少线程堆栈数。

● SetThreadPriority –

设置线程的优先级(LOW,BELOW LOW or HIGH)。

● GetThreadPriority – 获取线程的优先级。

在MFC中,并不是所有的成员函数都是类成员。我们也可以访问一些全局函数。这些函数都以Afx开头。在MFC的线程中,AfxBeginThread和AfxEndThread是运用的最广泛的函数。我们用AfxBeginThread函数创建线程。AfxBeginThread语法如下:

CWinThread* AfxBeginThread( AFX_THREADPROC ThreadProc, LPVOID Param,

int nPriority = THREAD_PRIORITY_NORMAL,UINT nStackSize = 0,

DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

ThreadProc是AfxBeginThread函数的第一个参数,我们在这个参数中使用线程函数的名称,在这个参数中传入void类型的参数指针,此函数的返回值类型是UINT。AfxBeginThread的其它参数是可选的。默认的优先级是THREAD_PRIORITY_NORMAL。当想要改变其优先级时,可以调用函数SetThreadPriority。我们同样也可以获得优先级。

AfxEndThread用来终止线程,AfxEndThread有一个退出代码参数列表。

CwinThread *pThread = AfxBeginThread( ThreadFunction, &data);

UINT ThreadFunction(LPVOID param)

{

DWORD result =0 ;

// do somthig

AfxEndThread(exitCode);

return result;

}

3.Win32的多线程

Win32的线程使用CreateThread函数来创建,CreateThread函数的语法如下:

HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,

DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,

LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);

当我们想终止线程的时候有下面几种方法:

(1)使用TerminateThread函数

(2)使用ExitThread函数

(3)使用return

但是Advanced

Windows建议我们使用Return方法。TerminateThread或ExitThread不能正确的清除线程堆栈。函数GetThreadTimes通常用来获取线程的运行时间。函数GetCurrentThreadID是获取当前线程的ID。Sleep指定线程休眠,单位为毫秒。比如,Sleep(1000)将使线程休眠1000毫秒。函数SwithToThread的功能是切换到其他线程。SuspendThread用来挂起一个线程。WaitForSingleObject等待一个指定的线程,直到线程完全完成它的工作。函数WaitForMultipleObject用来等待多个事件。等待的情形:更改通知、控制台输入、事件、工作、互斥、进程、信号量、线程和可等待定时器。

五.线程的优点

多线程运用程序使用100%的CPU效率。当我们创建一个进程,要需要更多的内存空间。多线程运用程序跟进程共享一个内存空间

转自:http://www.vckbase.com/document/viewdoc/?id=1978

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux下,C语言使用多线程可以通过pthread库来实现。下面是一个使用不同时间片和不同调度策略的示例: ```c #include <stdio.h> #include <pthread.h> void* increment(void* arg) { int i; for (i = 0; i < 5; i++) { printf("Thread 1: %d\n", i); } pthread_exit(NULL); } void* decrement(void* arg) { int i; for (i = 5; i > 0; i--) { printf("Thread 2: %d\n", i); } pthread_exit(NULL); } int main() { pthread_t tid1, tid2; pthread_attr_t attr1, attr2; // 初始化线程属性 pthread_attr_init(&attr1); pthread_attr_init(&attr2); // 设置线程1的时间片大小为10ms struct sched_param param1; param1.sched_priority = 0; pthread_attr_setschedparam(&attr1, &param1); pthread_attr_setschedpolicy(&attr1, SCHED_RR); // 使用循环调度策略 // 设置线程2的时间片大小为20ms struct sched_param param2; param2.sched_priority = 0; pthread_attr_setschedparam(&attr2, &param2); pthread_attr_setschedpolicy(&attr2, SCHED_FIFO); // 使用先进先出调度策略 // 创建线程1和线程2 pthread_create(&tid1, &attr1, increment, NULL); pthread_create(&tid2, &attr2, decrement, NULL); // 等待线程1和线程2结束 pthread_join(tid1, NULL); pthread_join(tid2, NULL); // 销毁线程属性 pthread_attr_destroy(&attr1); pthread_attr_destroy(&attr2); return 0; } ``` 在上面的示例中,我们创建了两个线程 `increment` 和 `decrement`,分别打印从0递增和从5递减的数字。我们使用 `pthread_attr_setschedparam` 函数来设置不同的时间片大小,并通过 `pthread_attr_setschedpolicy` 函数设置不同的调度策略。线程1使用了循环调度策略(SCHED_RR),时间片大小为10ms;线程2使用了先进先出调度策略(SCHED_FIFO),时间片大小为20ms。 请注意,设置时间片大小和调度策略可能需要在具有特权的状态下进行(例如,使用root用户)。另外,调度策略和时间片大小的实际效果也受到系统负载和其他因素的影响。以上示例仅为演示多线程使用不同时间片和调度策略的一种方式,结果可能因系统而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值