前些时间用了一次并行处理,发现还是挺好用的,效率提高了不少,今天另外一个任务,也采用了并行处理,代码(vs2015 MFC工程)的写法如下:
int m_tdcCount = 4;
int m_threadIndex;
void ATaskThread()
{
CString strText;
DWORD dwId;
int threadIndex;
{
autounlock();
threadIndex = m_threadIndex++;
dwId = GetCurrentThreadId();
strText.Format(TEXT("第%d个线程的ID号:%d = 0x%x.\n"), threadIndex, dwId, dwId);
OutputDebugString(strText);
}
Sleep(5000); // test only
... // 任务中的其它打印
... // my task process
{
autounlock();
m_tdcCount--;
}
}
void startMyTask()
{
CString strText;
m_tdcCount = 4;
m_threadIndex = 0;
strText.Format(TEXT("即将启动的处理线程数:%d.\n"), m_tdcCount);
OutputDebugString(strText);
#pragma omp parallel num_threads(m_tdcCount)
ATaskThread();
// 等待结束,其实这里应该不需要,因为实际上是前面的任务结束后才会到这里来
OutputDebugString(TEXT("开始等待所有任务线程结束...\n"));
while (m_tdcCount > 0)
Sleep(100);
... // 收尾工作
}
入口为 startMyTask(),其中采用并行建立了4个实际的任务处理线程ATaskThread()。过程中,采用全局变量m_tdcCount对任务的生命期进行控制:在建立线程之前设置为4,即4个线程,一个任务线程一旦完成自己的任务,就对该变量减1,所以当该变量减到0时,就表明了全部任务的结束。但实际调试过程中和想像的有点出入,于是就在任务线程中添加了一个 Sleep(5000),使线程等待足够长的时间,预期的打印:
即将启动的处理线程数:4.
第0个线程的ID号:67376 = 0x10730.
第1个线程的ID号:69524 = 0x10f94.
第2个线程的ID号:68112 = 0x10a10.
第3个线程的ID号:67736 = 0x10898.
开始等待所有任务线程结束...
<任务中的其它打印>
或者是“开始等待所有任务线程结束...”可能往前提但位于第一行的后面,这样都算正常,比如下面的也是正常的:
即将启动的处理线程数:4.
第0个线程的ID号:67376 = 0x10730.
开始等待所有任务线程结束...
第1个线程的ID号:69524 = 0x10f94.
第2个线程的ID号:68112 = 0x10a10.
第3个线程的ID号:67736 = 0x10898.
<任务中的其它打印>
因为任务线程中有个Sleep(5000),所以任务中的打印肯定应该排在"开始等待所有任务线程结束..."一行之后,但实际上打印却是如下示的样子:
即将启动的处理线程数:4.
第0个线程的ID号:67376 = 0x10730.
第1个线程的ID号:69524 = 0x10f94.
第2个线程的ID号:68112 = 0x10a10.
第3个线程的ID号:67736 = 0x10898.
<任务中的其它打印>
开始等待所有任务线程结束...
即所有的任务都运行完了才到调用ATaskThread()之后的地方。这样看,用起来就方便了,不需要控制并行任务线程,把它当作一个普通的函数调用即可,不用害怕其后的语句和线程任务同时运行。