CThread
CThread 简化了启动、运行和停止线程的过程。您可以像在 C# 或 Java 中那样使用它来处理线程。
引言
CThread
使在 MFC 中使用线程几乎可以与在 C#/Java 中使用线程的方式相同。您可以从 CThread
派生自己的类并实现 Run(void* )
。要启动线程,您必须调用 Start()
。现在,新线程将在 Run()
中开始其执行。当 Run()
完成时,线程将停止其执行。
使用代码
要使用该代码,您应该从 CThread
派生您的类。您还必须实现 Run
函数,线程将在其中执行。例如
class CMyThread : public CThread { void Run(void* param); }
如果您想从多个类派生,这是可以的,如果您想在对话框类中运行线程,这种情况很常见。
class CMyThread : public CDialog, CThread { void Run(void* param); }
启动线程
启动线程非常简单,只需调用 Start()
。现在,新线程将在 Run()
中开始其执行。如果线程已在运行,则不应调用 Start()
。要检查这一点,请调用 IsRunning()
。
您可以向线程发送一个可选的指针参数。如果您这样做,请确保该指针有效。以下示例将不起作用
{ int parameter = 10; Start(¶mater); }
当您调用 Start()
时,指针是有效的,但在线程开始执行时,它可能不总是有效的。请改用 new
。
{ int* parameter = new int(10); Start(¶mater); }
不要忘记在 Run()
中删除对象。参数以 void
指针的形式发送到 Run()
中的线程。您也可以使用成员变量将信息发送到线程。
停止线程
要停止线程,请调用 Stop()
。这将 **不会** 立即停止线程;而是设置一个标志,告诉线程停止其执行。如果您想等待线程退出,请调用 WaitForStop()
。
运行线程
线程需要做什么取决于您。线程将在您必须实现的 Run()
函数中开始执行。当线程退出 Run()
时,它将完成其执行。在实现 Run()
时,您必须检查线程是否应停止执行。如果某个线程调用了 Stop()
,则为真。要检查该标志,请调用 ShouldRun()
。例如
void CMyThread::Run(void* param) { //Run the thread until someone has called Stop() while( ShouldRun() ) { ... } }
从线程发送消息
很多时候您想从线程更新 GUI。例如,您想更新一个进度条。最直接的解决方案是从线程直接更新进度条。例如
void CMyThreadInDialog::Run(void* param) { ... m_progressbar.SetPos(10) ... }
但这 **不会** 起作用。Windows 的一个黄金法则是,只有一个线程应该操作 GUI。为此,您应该使用消息。从在 Run()
中执行的线程,您应该向主线程发送一条消息,告诉窗口进行更新。您 **不** 应该使用 SendMessage
,而应该使用 PostMessage
。SendMessage
直接从线程更新 GUI,这并非您想要的。PostMessage
将消息添加到窗口的消息队列中,并将由主线程处理。
所以您的代码应该看起来像这样
void CMyThreadInDialog::Run(void* param) { ... ::PostMessage(UPDATE_PROGRESSBAR, m_hWnd, 10, 0); ... }
有关更多详细信息,请参阅示例。
关注点
在我编写这个类之前,我在 CodeProject 上寻找过类似的东西。令我惊讶的是,我没有找到关于这个主题的文章。但我没有足够努力地寻找……至少有两篇文章提供了类似的解决方案
即使我不是第一个撰写有关此主题的文章的人,我也希望有人会发现这个类很有用 :-)
历史
- 2005年7月30日 - 版本 1.0。初始版本。
- 2005年8月21日 - 版本 1.01。Blake Miller 建议的次要修复和改进。