CWinThread::PreTranslateMessage
在消息调度到 Windows 函数
TranslateMessage
和
DispatchMessage
之前筛选消息。
CWinThread::ProcessMessageFilter
在某些消息到达应用程序之前截获这些消息。
CWinThread::ProcessWndProcException
截获由线程的消息和命令处理程序引发的所有未经处理的异常。
CWinThread::PumpMessage
包含线程的消息循环。
CWinThread::ResumeThread
递减线程的挂起计数。
CWinThread::Run
具有消息泵的线程的控制函数。 替代以自定义默认消息循环。
CWinThread::SetThreadPriority
设置当前线程的优先级。
CWinThread::SuspendThread
递增线程的挂起计数。
公共运算符
执行的主线程通常由派生自
CWinApp
的对象提供;
CWinApp
派生自
CWinThread
。 其他
CWinThread
对象允许一个给定应用程序中存在多个线程。
CWinThread
支持两种常规类型的线程:工作线程和用户界面线程。 工作线程没有消息泵:例如在电子表格应用程序中执行后台计算的线程。 用户界面线程具有消息泵,并处理从系统接收的消息。
CWinApp
和派生自它的类是用户界面线程的示例。 其他用户界面线程也可以直接派生自
CWinThread
。
类
CWinThread
的对象通常存在于线程的持续时间内。 如果要修改此行为,请将
m_bAutoDelete
设置为
FALSE
。
CWinThread
类是使代码和 MFC 完全线程安全所必需的。 框架用来维护特定于线程的信息的线程本地数据由
CWinThread
对象管理。 由于通过这种对
CWinThread
的依赖来处理线程本地数据,因此,使用 MFC 的任何线程必须由 MFC 创建。 例如,运行时函数
_beginthread
、
_beginthreadex
创建的线程不能使用任何 MFC API。
若要创建线程,请调用
AfxBeginThread
。 有两种形式,具体取决于你是需要工作线程还是用户界面线程。 如果需要用户界面线程,请传递给
AfxBeginThread
指向
CWinThread
派生类的
CRuntimeClass
的指针。 如果要创建工作线程,请传递给
AfxBeginThread
指向控制函数的指针和控制函数的参数。 对于工作线程和用户界面线程,可以指定用于修改优先级、堆栈大小、创建标志和安全特性的可选参数。
AfxBeginThread
将返回指向新
CWinThread
对象的指针。
通过改为调用
AfxBeginThread
,可以构造
CWinThread
派生的对象,然后调用
CreateThread
。 如果要在连续创建和终止线程执行之间重复使用
CWinThread
对象,则此双阶段构造方法非常有用。
有关
CWinThread
的详细信息,请参阅文章
使用 C++ 和 MFC 进行多线程处理
、
多线程处理:创建用户界面线程
、
多线程处理:创建工作线程
和
多线程处理:如何使用同步类
。
继承层次结构
CObject
CCmdTarget
CWinThread
标头:
afxwin.h
CWinThread::CreateThread
创建要在调用进程的地址空间内执行的线程。
BOOL CreateThread(
DWORD dwCreateFlags = 0,
UINT nStackSize = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
dwCreateFlags
指定一个用于控制线程创建的额外标志。 此标志可以包含两个值之一:
CREATE_SUSPENDED
以 1 的挂起计数启动线程。 如果要在线程开始运行之前初始化 CWinThread
对象的任何成员数据(例如 m_bAutoDelete
或派生类的任何成员),请使用 CREATE_SUSPENDED
。 初始化完成后,使用 CWinThread::ResumeThread
启动线程运行。 在调用 CWinThread::ResumeThread
之前,线程将不会执行。
0 创建后立即启动线程。
nStackSize
指定新线程堆栈的大小(以字节为单位)。 如果为 0,堆栈大小会默认为与进程主线程的大小相同的大小。
lpSecurityAttrs
指向用于指定线程安全特性的 SECURITY_ATTRIBUTES
结构。
如果线程创建成功,则为非零值;否则为 0。
使用 AfxBeginThread
创建线程对象并在一个步骤中执行它。 如果要在连续创建和终止线程执行之间重复使用线程对象,请使用 CreateThread
。
CWinThread::CWinThread
构造 CWinThread
对象。
CWinThread();
若要开始线程的执行,请调用 CreateThread
成员函数。 通常通过调用 AfxBeginThread
来创建线程,这将调用此构造函数和 CreateThread
。
CWinThread::ExitInstance
由框架从很少替代的 Run
成员函数中调用以退出线程的此实例,或者在调用 InitInstance
失败时由框架调用。
virtual int ExitInstance();
线程的退出代码;0 表示无错误,大于 0 的值表示错误。 可以通过调用 GetExitCodeThread
来检索此值。
不要从除了 Run
成员函数内以外的任何位置调用此成员函数。 此成员函数仅在用户界面线程中使用。
如果 m_bAutoDelete
为 TRUE
,此函数的默认实现将删除 CWinThread
对象。 如果要在线程终止时执行其他清理,请替代此函数。 ExitInstance
的实现应在代码执行后调用基类的版本。
CWinThread::GetMainWnd
如果应用程序是 OLE 服务器,请调用此函数来检索指向应用程序的活动主窗口的指针,而不是直接引用应用程序对象的 m_pMainWnd
成员。
virtual CWnd* GetMainWnd();
此函数返回指向两种类型的窗口之一的指针。 如果线程是 OLE 服务器的一部分,并且具有在活动容器中处于就地活动状态的对象,则此函数将返回 CWinThread
对象的 CWinApp::m_pActiveWnd
数据成员。
如果没有在容器中处于就地活动状态的对象,或者你的应用程序不是一个 OLE 服务器,则此函数返回你的线程对象的 m_pMainWnd
数据成员。
对于用户界面线程,这等效于直接引用应用程序对象的 m_pActiveWnd
成员。
如果您的应用程序不是 OLE 服务器,调用此函数相当于直接引用应用程序对象的 m_pMainWnd
成员。
替代此函数以修改默认行为。
CWinThread::GetThreadPriority
获取此线程的当前线程优先级别。
int GetThreadPriority();
其优先级类中的当前线程优先级别。 返回的值将是以下值之一,从最高优先级到最低优先级列出:
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_IDLE
有关这些优先级的详细信息,请参阅 Windows SDK 中的 SetThreadPriority
。
CWinThread::InitInstance
必须替代 InitInstance
才能初始化用户界面线程的每个新实例。
virtual BOOL InitInstance();
如果初始化成功,则为非零值;否则为 0。
通常,你会替代 InitInstance
以执行在首次创建线程时必须完成的任务。
此成员函数仅在用户界面线程中使用。 在传递给 AfxBeginThread
的控制函数中执行工作线程初始化。
CWinThread::IsIdleMessage
替代此函数,使 OnIdle
在特定消息生成后不被调用。
virtual BOOL IsIdleMessage(MSG* pMsg);
指向正在处理的当前消息。
如果在处理消息后应调用 OnIdle
,则为非零值;否则为 0。
默认实现不会在冗余鼠标消息和由闪烁的插入符生成的消息后调用 OnIdle
。
如果应用程序创建了短计时器,则将经常调用 OnIdle
,从而导致性能问题。 若要提高此类应用程序的性能,请在应用程序的 CWinApp
派生类中替代 IsIdleMessage
以检查 WM_TIMER
消息,如下所示:
BOOL CMyWinApp::IsIdleMessage(MSG* pMsg)
if (!CWinApp::IsIdleMessage(pMsg) || pMsg->message == WM_TIMER)
return FALSE;
return TRUE;
以这种方式处理 WM_TIMER
将提高使用短计时器的应用程序的性能。
CWinThread::m_bAutoDelete
指定 CWinThread
对象是否应在线程终止时自动删除。
BOOL m_bAutoDelete;
m_bAutoDelete
数据成员是 BOOL 类型的公共变量。
m_bAutoDelete
的值不会影响基础线程句柄的关闭方式,但它会影响关闭句柄的计时。 在销毁 CWinThread
对象时,始终关闭线程句柄。
CWinThread::m_hThread
附加到此 CWinThread
的线程的句柄。
HANDLE m_hThread;
m_hThread
数据成员是 HANDLE
类型的公共变量。 仅当基础内核线程对象当前存在且句柄尚未关闭时,它才有效。
CWinThread
析构函数对 m_hThread
调用 CloseHandle
。 如果当线程终止时 m_bAutoDelete
为 TRUE
,CWinThread
对象会被销毁,这将使指向 CWinThread
对象及其成员变量的任何指针失效。 可能需要 m_hThread
成员来检查线程退出值,或等待信号。 若要在线程执行期间以及线程终止后保留 CWinThread
对象及其 m_hThread
成员,请在允许线程执行继续之前将 m_bAutoDelete
设置为 FALSE
。 否则,在你尝试使用它之前,线程可能会终止、销毁 CWinThread
对象,并关闭句柄。 如果使用此方法,则需要负责删除 CWinThread
对象。
CWinThread::m_nThreadID
附加到此 CWinThread
的线程的 ID。
DWORD m_nThreadID;
m_nThreadID
数据成员是 DWORD
类型的公共变量。 仅当基础内核线程对象当前存在时,它才有效。
另请参阅有关 m_hThread
生存期的注解。
请参阅 AfxGetThread
的示例。
CWinThread::m_pActiveWnd
使用此数据成员来存储指向线程的活动窗口对象的指针。
CWnd* m_pActiveWnd;
当 m_pActiveWnd
引用的窗口关闭时,Microsoft 基础类库将自动终止你的线程。 如果此线程是应用程序的主线程,则应用程序也将终止。 如果此数据成员是 NULL
,则将继承应用程序的 CWinApp
对象的活动窗口。 m_pActiveWnd
是 CWnd*
类型的公共变量。
通常,在替代 InitInstance
时将设置此成员变量。 在工作线程中,此数据成员的值继承自其父线程。
CWinThread::m_pMainWnd
使用此数据成员来存储指向线程的主窗口对象的指针。
CWnd* m_pMainWnd;
当 m_pMainWnd
引用的窗口关闭时,Microsoft 基础类库将自动终止你的线程。 如果此线程是应用程序的主线程,则应用程序也将终止。 如果此数据成员是 NULL
,则应用程序的 CWinApp
对象的主窗口将用于确定何时终止线程。 m_pMainWnd
是 CWnd*
类型的公共变量。
通常,在替代 InitInstance
时将设置此成员变量。 在工作线程中,此数据成员的值继承自其父线程。
CWinThread::OnIdle
替代此成员函数以执行空闲时间处理。
virtual BOOL OnIdle(LONG lCount);
lCount
每当线程的消息队列为空而调用 OnIdle
时将递增的计数器。 每次处理新消息时,此计数将重置为 0。 可以使用 lCount
参数来确定在未处理消息的情况下线程空闲时间的相对长度。
如果接收更多空闲处理时间,则为非零值;如果不再需要更多空闲处理时间,则为 0。
当线程的消息队列为空时会在默认消息循环中调用 OnIdle
。 使用替代以调用自己的后台空闲处理程序任务。
OnIdle
应返回 0 以指示不需要额外的空闲处理时间。 每当消息队列为空而调用 OnIdle
时,lCount
参数将递增,并且在每次处理新消息时将重置为 0。 可以基于此计数调用不同的空闲例程。
此成员函数的默认实现将从内存中释放临时对象和未使用的动态链接库。
此成员函数仅在用户界面线程中使用。
由于应用程序在 OnIdle
返回之前无法处理消息,因此不要在此函数中执行冗长的任务。
CWinThread::operator HANDLE
检索 CWinThread
对象的句柄。
operator HANDLE() const;
如果成功,则为线程对象的句柄;否则为 NULL
.
使用句柄直接调用 Windows API。
CWinThread::PostThreadMessage
调用以将用户定义的消息发布到另一个 CWinThread
对象。
BOOL PostThreadMessage(
UINT message,
WPARAM wParam,
LPARAM lParam);
message
用户定义的消息的 ID。
wParam
第一个消息参数。
lParam
第二个消息参数。
如果成功,则不为 0;否则为 0。
已发布的消息由消息映射宏 ON_THREAD_MESSAGE
映射到正确的消息处理程序。
调用 PostThreadMessage
时,消息将放置在线程的消息队列中。 但是,由于以这种方式发布的消息与窗口不关联,因此 MFC 不会将它们调度到消息或命令处理程序。 为了处理这些消息,请替代 CWinApp
派生类的 PreTranslateMessage()
函数,并手动处理消息。
CWinThread::PreTranslateMessage
替代此函数,以在窗口消息调度到 Windows 函数 TranslateMessage
和 DispatchMessage
之前筛选这些消息。
virtual BOOL PreTranslateMessage(MSG* pMsg);
指向包含要处理的消息的 MSG
结构。
如果消息已在 PreTranslateMessage
中完全处理且不应进一步处理,则为非零值。 如果消息应以正常方式处理,则为零。
此成员函数仅在用户界面线程中使用。
CWinThread::ProcessMessageFilter
框架的挂钩函数调用此成员函数来筛选和响应某些 Windows 消息。
virtual BOOL ProcessMessageFilter(
int code,
LPMSG lpMsg);
指定挂钩代码。 此成员函数使用此代码来确定如何处理 lpMsg
。
lpMsg
指向 Windows MSG
结构的指针。
如果消息已处理,则为非零值;否则为 0。
挂钩函数将在事件发送到应用程序的正常消息处理之前处理事件。
如果替代此高级功能,请确保调用基类版本以维护框架的挂钩处理。
CWinThread::ProcessWndProcException
每当处理程序不捕获线程的消息或命令处理程序之一中引发的异常时,框架都会调用此成员函数。
virtual LRESULT ProcessWndProcException(
CException* e,
const MSG* pMsg);
指向未处理的异常。
指向 MSG
结构,其中包含有关导致框架引发异常的 Windows 消息的信息。
如果生成 WM_CREATE
异常,则为 -1;否则为 0。
请勿直接调用此成员函数。
此成员函数的默认实现仅处理从以下消息生成的异常:
PumpMessage
包含线程的消息循环。 PumpMessage
由 CWinThread
调用以泵出线程的消息。 可以直接调用 PumpMessage
以强制处理消息,也可以替代 PumpMessage
以更改其默认行为。
仅建议高级用户直接调用 PumpMessage
并替代其默认行为。
CWinThread::ResumeThread
调用以恢复执行由 SuspendThread
成员函数挂起的线程或使用 CREATE_SUSPENDED
标志创建的线程。
DWORD ResumeThread();
如果成功,则为线程的上一个挂起计数;否则为 0xFFFFFFFF
。 如果返回值为零,则当前线程未挂起。 如果返回值为 1,则线程已挂起,但现在将重新启动。 任何大于 1 的返回值都表示线程保持挂起状态。
当前线程的挂起计数减 1。 如果挂起计数减到 0,线程将恢复执行;否则线程将保持挂起状态。
CWinThread::Run
为用户界面线程提供默认消息循环。
virtual int Run();
由线程返回的 int
值。 可以通过调用 GetExitCodeThread
来检索此值。
Run
会获取并调度 Windows 消息,直到应用程序接收 WM_QUIT
消息为止。 如果线程的消息队列当前不包含任何消息,Run
会调用 OnIdle
以执行空闲时间处理。 传入消息将转到 PreTranslateMessage
成员函数进行特殊处理,然后转到 Windows 函数 TranslateMessage
进行标准键盘转换。 最后,将调用 DispatchMessage
Windows 函数。
尽管 Run
很少被替代,但可以替代它来实现特殊行为。
此成员函数仅在用户界面线程中使用。
CWinThread::SetThreadPriority
此函数在其优先级类中设置当前线程的优先级别。
BOOL SetThreadPriority(int nPriority);
nPriority
在其优先级类中指定新的线程优先级别。 此参数必须是以下值之一,从最高优先级到最低优先级列出:
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_IDLE
有关这些优先级的详细信息,请参阅 Windows SDK 中的 SetThreadPriority
。
如果函数成功,则为非零值;否则为 0。
它只能在 CreateThread
成功返回后调用。
CWinThread::SuspendThread
递增当前线程的挂起计数。
DWORD SuspendThread();
如果成功,则为线程的上一个挂起计数;否则为 0xFFFFFFFF
。
如果任何线程的挂起计数高于零,该线程将不会执行。 可以通过调用 ResumeThread
成员函数来恢复线程。
CCmdTarget
类
层次结构图
CWinApp
类
CCmdTarget
类