C++ 中的高效线程——第 2 部分:ExitableThread 类






2.18/5 (5投票s)
2006年11月22日
2分钟阅读

25601

616
将 Win32 线程 API 封装到 C++ 友好的类中。
引言
在过去的几年中,多线程应用程序已成为我开发的主力。我甚至发现自己在不需要的地方编写多线程应用程序。工作线程允许 Win32 应用程序改善用户体验并提高性能。
凭借这种丰富的经验,我总结了一套经常使用的模式(好吧,它们不是经典意义上的模式;更像是范例)。我编写了一些类,可以简化在所有情况下使用这些范例。
在本三篇文章系列的第 2 部分中,我将展示这些范例中最常用的一个:可退出线程范例。大多数工作线程在某种循环中一遍又一遍地执行相同的操作。无论是处理多个不同的文件、将数据从一种格式导出到另一种格式,还是读取通过线路传输的消息,这些操作都有非常特定的节奏。
可退出线程模式的描述
可退出线程模式的基础是将线程与 Win32 事件对象配对。此事件对象在外部事件(用户按下取消按钮、应用程序关闭等)发出信号之前不会发出信号。在工作线程的每次迭代开始或结束时,线程都会检查退出事件。如果设置了该事件,则它会退出循环,执行任何需要的清理。
ExitableThread 类
ExitableThread
类继承自本系列第 1 篇文章中创建的 Thread
类。 这使我们可以利用基本线程创建和方法调用的代码,同时添加退出事件对象和相关方法。
template<class T, class P> class ExitableThread : public Thread<T, P> { public: typedef void (T::*ThreadFunc)( P ); ExitableThread(); virtual ~ExitableThread(); // ExitThread methods - Called within the context of an // external thread to instruct the embedded (running) // thread to exit. // // ExitThread() - Signals the event and immediately // returns. // // ExitThreadAndWait() - Signals the event and waits // until the thread actually exits or the timeout // expires. Returns true if the thread exited, or // false if the timeout expired void ExitThread(); bool ExitThreadAndWait( DWORD timeoutMS = 5000 ); // IsExitEventSet - Called by the embedded (running) // thread to test if the exit event is set. Returns // true if the event has been set, and the thread // should exit, and false otherwise bool IsExitEventSet(); };
注释说明了代码。新的 ExitThread()
方法允许其他线程等待封装的线程退出。这些方法设置线程的退出事件。ExitThread()
方法设置事件并立即返回到调用者,而 ExitThreadAndWait()
等待线程句柄变为已发出信号。 如果它没有在指定的超时时间过去之前退出,则该线程将被终止。
使用 ExitableThread 类
ExitableThread
类的使用方式与 Thread
父类相同。但是,工作线程的方法应该是一个迭代过程,它会定期调用 IsExitEventSet()
方法以查看是否应该退出。
void TestClass::DoExitableWork( int i ) { Files::iterator it; for (it = files.begin(); it != files.end(); it++) { ProcessFile( *it ); // Check the Exit Event if (m_thread.IsExitEventSet()) break; } }
结论
可退出线程是一种模式(或范例),可帮助控制工作线程及其生命周期。当外部情况需要线程退出时,可退出线程模式允许工作线程获取消息并正确清理并释放任何资源。ExitableThread
类允许在需要迭代工作线程的任何地方轻松插入此模式。
在这个简短系列的最后一部分中,我们将研究如何将 Thread
和 ExitableThread
类扩展为一组强大的类,从而消除对调用者和被调用者的任何假设。
历史
- 2006.11.22 - 第一次修订。