2014-07-25 61 views
0

在我的一个MFC应用程序中有几个工作线程。这些线程的性质如下:在MFC中使用WaitForSingleObject和CEvent进行线程协调

  1. 大多数线程执行一次它们的任务,并等待一个条件为真,以便进一步执行。
  2. 在少数情况下,线程会无限等待,直到条件成立为止,并且在其他情况下,它会等待一定的时间段,并根据条件成为真期间或期限届满(以先发生者为准),然后再开始等待。

  3. 线程必须在应用程序的整个生命周期中运行,但不一定每时每刻都在运行。

当前每个线程都有一个无限循环,它执行它的任务;因为每个线程必须在整个应用程序的生命周期中工作,所以我不想每次关闭这些线程并重新创建。在循环内部,我使用了带有自动重置CEvent的WaitForSingleObject来实现这种线程协调。 CEvent对象通过任何线程或UI线程发出信号。

在这种情况下,我有以下查询:

i。这种方法对我的要求是否合理?

ii。为此目的使用这么多CEvent对象是否有任何重大开销。 有没有更好的选择?

iii。在某些情况下,线程会无限等待CEvent对象发出信号,并且该对象仅在从另一个线程接收到消息后才从Windows消息处理程序发出信号。消息通过PostMessage接收。在这里,我担心失去从线程发送的消息。如果消息处理程序跳过消息,则它不能指示CEvent对象,并且等待的线程必须无限等待。必须采取什么预防措施来避免这种情况?有没有更好的方法来重建计划?

请给我一些更好的选择。

回答

0

你的方法很好。不要担心多个CEvent对象。在你的情况下,你必须每个线程至少有一个事件。

我不确定你用什么方法退出线程。但是您可能需要额外的CEvent对象来检测您是否必须优雅地退出线程。因此,在这种情况下,您将在每个线程中使用WaitForMultipleObjects(1个事件将运行或不运行,另一个事件将退出线程或不)。

如果线程太多,我建议您在需要时生成子线程。子线程只会运行一次并退出。在父线程中,您将再次等待以查看哪个子线程必须运行。您可以根据事件对象数组来检测要产生哪个线程。这种方法将占用较少的系统资源。

0

使用WaitForMultipleObjects而不是WaitForSingleObject。每个事件数组中的第一个事件应该是设置为关闭应用程序的全局CEvent。每个线程检测到这个事件,并通过从线程函数返回干净地退出。

设置关闭事件(通常在OnClose中)后,使用线程句柄上的WaitForMultipleObjects等待所有辅助线程关闭。这确保线程可能访问的任何全局数据都保持分配状态,直到线程消失。

+0

我认为你的答案只解释了如何以清洁的方式关闭应用程序。主线程可以确保所有工作线程已成功退出;因此现在是释放所有全球资源并退出的时候了。我以不同的方式使用布尔变量来实现它,但是这并不能确保在取消分配这些线程使用的全局数据之前正确关闭工作线程。虽然它非常清楚如何实现,请给出一些实现这个想法的代码片段?您对我的帖子中的查询有任何建议吗? – Sukhendu

0

在我的应用程序中,我只使用10到12个工作线程。我在某个地方看到 当一个线程调用一个等待函数时,它从用户模式进入内核模式。由于进入内核模式需要大约1000个处理器周期,这在具体情况下可能太昂贵,这是有点昂贵的。

但是,正如goths和ScottMcP所建议的那样,我使用WaitForMultipleObjects而不是WaitForSingleObject以下面的方式确保在清理线程使用的任何资源之前进行正常的线程关闭。

CEvent doWork,exitThread; //Auto reset events 
CWinThread* MyThread; 
UINT MyThreadFunction(LPVOID param); 

BOOL CMyDlg::OnInitDialog() 
{ 
    //Other initialization code 
    MyThread=AfxBeginThread(MyThreadFunction, CMyDlg::GetSafeHwnd()); 
    //Any other initialization code 
    return TRUE; 
} 

UINT MyThreadFunction(LPVOID param) 
{ 
HANDLE waitEvents[2]; 
waitEvents[0]=doWork; 
waitEvents[1]=exitThread; 
while(true) 
{ 

    DWORD stat=::WaitForMultipleObjects(2, waitEvents, FALSE, INFINITE); 
    switch(stat) 
    { 
    case WAIT_OBJECT_0 + 0: 
     // doWork CEvent is signalled; proceed to do some work 
    break; 

    case WAIT_OBJECT_0 + 1: 
     //exitThread is signalled; so exit from this thread handler function 
    return 0; 

    case WAIT_FAILED: 
     // failure may be related to wrong handles passed for lpHandles 
    break; 

    case WAIT_TIMEOUT: 
     // not applicable here because dwMilliseconds parameter is set to INFINITE 
    break; 
    } 
} 
return 0; 
} 

CMyDlg::OnClose() 
{ 
    exitThread.SetEvent(); 
    DWORD Stat=WaitForSingleObject(MyThread->m_hThread, INFINITE); 
    if(Stat==WAIT_OBJECT_0) 
    { 
    //Thread supposed to be Exited 
    //Cleanup allocated resources here 
    } 
    else if(Stat==WAIT_TIMEOUT) 
    { 
    //not applicable here 
    } 
    else if(Stat==WAIT_FAILED) 
    { 
    //Invalid thred handle passed or something else 
    } 
    EndDialog(0); 
} 

请检查我的答案,如果发现任何错误或有任何改进的范围。

相关问题