姓名:李振华 学号:17101223418
【嵌牛导读】:Microsoft 基础类 (MFC) 库提供多线程应用程序支持。进程是应用程序的执行实例。线程是进程内的执行路径。线程又分为工作线程和界面线程。
【嵌牛鼻子】:复杂的应用程序必定会用到线程开发,而Windows系统是以消息驱动的系统,所以掌握线程的相关知识尤为重要。
【嵌牛提问】:如何利用界面线程实时更新界面?如何将消息由工作线程发送给界面线程?如何将绑定消息函数?
【嵌牛正文】:
进程是应用程序的执行实例。 例如,双击“记事本”图标时,将启动运行“记事本”的进程。
线程是进程内的执行路径。 启动“记事本”时,操作系统创建进程并开始执行该进程的主线
程。 此线程终止时,进程也终止。 启动代码以函数地址的形式将此主线程提供给操作系统。 通常是所提供的 main 函数或 WinMain 函数的地址。
如果愿意,可以在应用程序中创建其他线程。 如果在处理后台任务或维护任务时不希望用户等待这些任务完成,则可能需要创建其他线程。 MFC 应用程序中的所有线程都由CWinThread 对象表示。 大多数情况下,甚至不必显式创建这些对象,而只需调用框架 Helper 函数AfxBeginThread,该函数将为您创建CWinThread
对象。
MFC 区分两种类型的线程:用户界面线程和辅助线程。 用户界面线程通常用于处理用户输入及响应用户生成的事件和消息。 辅助线程通常用于完成不需要用户输入的任务(如重新计算)。 Win32 API 不区分线程类型;它只需要了解线程的起始地址以开始执行线程。 MFC 为用户界面中的事件提供消息泵,从而对用户界面线程进行专门处理。 CWinApp 是用户界面线程对象的一个示例,因为它从 CWinThread 派生并对用户生成的事件和消息进行处理。
应特别注意以下情况:
可能有不止一个线程需要访问同一对象。
多线程处理:编程提示 介绍了一些可以避免在这些情况下可能发生的问题的技术。
多线程处理:如何使用同步类说明如何使用可用的类从多个线程同步访问一个对象。
1、多线程处理:创建用户界面线程
用户界面线程通常用于处理用户输入和响应用户事件,这些行为独立于执行该应用程序其他部分的线程。 已经创建并启动主应用程序线程(在 CWinApp 导出的类中提供)。 下面描述创建其他用户界面线程所需的步骤。
创建用户界面线程时,必须首先从 CWinThread 派生类。 必须使用DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 宏声明并实现此类。 此类必须重写某些函数,也可以重写其他函数。
下表列出了这些函数及其用途。
创建用户界面线程时要重写的函数
功能 | 用途 |
---|---|
ExitInstance | 线程终止时执行清除。 通常重写。 |
InitInstance | 执行线程实例初始化。 必须重写。 |
OnIdle | 执行线程特定的闲置时间处理。 通常不重写。 |
PreTranslateMessage | 将消息调度到TranslateMessage和DispatchMessage之前对其进行筛选。 通常不重写。 |
ProcessWndProcException | 截获由线程的消息和命令处理程序引发的未经处理的异常。 通常不重写。 |
运行 | 控制线程的函数。 包含消息泵。 一般不重写。 |
MFC提供了AfxBeginThread
两个参数重载版本:一个只能创建工作线程,另一个既可创建用户界面线程也可创建工作线程。 若要启动用户界面线程,请调用AfxBeginThread的第二个重载,提供下列信息:
-
从
CWinThread
派生的类的RUNTIME_CLASS。 -
(可选)所需的优先级级别。 默认值为正常优先级。 有关可用的优先级级别的更多信息,请参见 Windows SDK 中的SetThreadPriority。
-
(可选)所需的线程堆栈大小。 默认值与创建线程的堆栈大小相同。
-
(可选)CREATE_SUSPENDED,如果希望在挂起状态中创建线程。 默认值为 0,即正常启动线程。
-
(可选)所需的安全特性。 默认值与父线程具有相同的访问权。 有关此安全信息格式的更多信息,请参见 Windows SDK 中的SECURITY_ATTRIBUTES。
AfxBeginThread
为您完成大部分工作。 它创建类的新对象、使用您提供的信息初始化该对象并调用CWinThread::CreateThread开始执行线程。 在整个过程中进行检查,确保假如创建过程的任何部分出现故障,所有对象都能被正确地解除分配。
一般创建过程如下:
先定义一个工作函数,一般来说你的线程就是依照该函数的功能执行任务:
UINT MyThreadFunction( LPVOID pParam )
{
//函数体
return 0;
}
然后可以按以下方式创建线程:
CWinThread* MyThread=AfxBeginThread(MyThreadFunction , pParam , THREAD_PRIORITY_NORMAL , 0 , 0 , NULL);
4、线程的等待与唤醒
(1)让线程等待(暂时挂起):
MyThread->SuspendThread();
(2)唤醒暂停的线程:
MyThread->ResumeThread();
5、查看线程状态:
DWORD code;
GetExitCodeThread(MyThread->m_hThread , &code);
if(code==STILL_ACTIVE){//线程仍在执行}
else {//线程停止执行}
6、结束线程
TerminateThread(MyThread->m_hThread , 0);
网友评论