用Windows API写线程,最痛苦的莫过于:
1. 记不住CreateThread长长的参数,对于普通人,参数超过3个,就变得很难记住了。
2. 线程参数表只有一个LPVOID,多参数情况下,我需要将其封装在类或者结构体里。
3. 变量的同步与异常处理。
比如我想创建两个线程,第一个线程输出: Thread1 : 1 ~ Thread1: 5;第二个线程接着输出:Thread2 : 6 ~ Thread2 : 10。两个线程共用一个int变量,从1递增到10。输出如下图:
、
以下是我用WIN32 API写的代码,是不是觉得比较麻烦?对于多参数,我痛恨每次都要写个struct指针来将其传递给线程,为什么线程不能是多参数的?Windows窗口消息起码还包括了WPARAM和LPARAM两个参数。
#include <windows.h> #include <iostream> #include <string> using namespace std; struct MyStruct { string str; volatile int* nIndex; }; CRITICAL_SECTION CK; DWORD WINAPI Win32_Thread(LPVOID pStruct) { EnterCriticalSection(&CK); MyStruct* myStruct = (MyStruct*)(pStruct); for (int i = 0; i < 5; ++i) { cout << myStruct->str << ": " << ++(*myStruct->nIndex) << endl; } LeaveCriticalSection(&CK); return 0; } int main() { // 创建临界区。 ::InitializeCriticalSection(&CK); // 创建第一个线程,输出Thread1。 MyStruct myStruct; myStruct.nIndex = new int; *myStruct.nIndex = 0; myStruct.str = "Thread1"; DWORD dwID1, dwID2; ::CreateThread(NULL, 0, &Win32_Thread, &myStruct, 0, &dwID1); // 创建第二个线程,输出Thread2。 MyStruct myStruct2; myStruct2.nIndex = myStruct.nIndex; myStruct2.str = "Thread2"; ::CreateThread(NULL, 0, &Win32_Thread, &myStruct2, 0, &dwID2); // 等待两个线程结束。 ::Sleep(3000); // 销毁临界区及新建的指针。 DeleteCriticalSection(&CK); delete myStruct.nIndex; myStruct.nIndex = NULL; getchar(); return 0; }
#include <windows.h> #include <iostream> #include <boost/thread.hpp> #include <boost/atomic.hpp> #include <boost/ref.hpp> using namespace std; using namespace boost; mutex io_mutex; // 线程print,不再需要DWORD WINAPI这个声明了。 // 当然LPVOID也消失了,thread类最多支持9个参数。 void print(atomic_int& nIndex, const string& str) { mutex::scoped_lock lock(io_mutex); for (int i = 0; i < 5; ++i) { cout << str << ": " << ++(nIndex) << endl; } } int main() { // 原子操作。 atomic_int nIndex = 0; // 创建两个线程,传入两个参数,一个是nIndex的引用,另一个是字符串。 thread(print, boost::ref(nIndex), "Hello"); thread(print, boost::ref(nIndex), "Boost"); getchar(); return 0; }输出结果如下:
短短几行代码,就完成了该功能,是不是很有效率?不仅如此,我还发现了其他优点:
1. 临界区的编写不再有初始化和释放等操作,这将有利于异常处理。
2. 从头到尾没有见到指针的声明与操作,指针传递被boost::ref()替代了。
3. 支持多参数传递,最大传递的参数个数为9个;
4. 只要是个函数,都可以将其用作线程,而不再需要格式化的声明为:DWORD WINAPI fun(LPVOID lpPram);
小结:在日常工作中,如果涉及到线程的开发,不妨先考虑下Boost库。
原文:http://blog.csdn.net/renstarone/article/details/19823495