用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
#include
#include
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
#include
#include
#include
#include
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库。