2016-07-06 22 views
1

我需要在類Foo中收到某個觸發器事件時產生一個線程。觸發器事件由Winsock服務器類接收,該類服務器引用了變量triggerEvent線程在面向對象的事件驅動的應用程序中

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     // Other things are done at the top of this loop 

     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       // I instantiate an object here to do 
       // what I need to do in the thread. 
       // I use a pointer that is a private 
       // member of Foo. 
       thingMaker = new ThingMaker(params); 

       // Spawn a new thread here calling a 
       // function of ThingMaker and using thingMaker 
       break; 
      } 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

由於線程局部其在switch情況下,我無法訪問它break。我不能撥打join(),因爲我正在處理實時處理,不能等待線程完成,除非我知道它已經完成。

我最近問了一個關於線程here關於同樣的應用程序的問題,並被告知detach()是不好的做法;我也認爲我的問題太模糊了,因爲提供的解決方案最終不符合我的需求,而且我的應用程序因此在架構上發生了變化。

我也試圖封裝線程在短生命管理器類中創建ThingMaker的實例,但無濟於事。

我該如何解決這個問題?我懷疑我的主要問題是範圍,但我的選擇是有限的。 Foo::HandleEvents()不能被延遲,否則我會丟失關鍵數據。

+3

您是否考慮過一個系統,您可以控制線程生命週期,例如線程池,在該線程池中發佈的代碼將您的'params'發佈到池監控的隊列中,以便分派工作? – WhozCraig

+0

如何處理'期貨'?你有C++ 11嗎? – Arunmu

+1

爲什麼不讓'thread'成爲'Foo'類的成員,那麼你總是可以訪問它?我有一個問題,如果在觸發'HandleEvent'函數時線程仍在執行,您希望發生什麼?您可能需要數據成員來跟蹤所有未完成的線程... –

回答

1

你可以使用一個std::map(或其他類似容器之一):

class Foo 
{ 
    bool HandleEvents(); 
    std::map<ThingMaker*, std::thread> m_map; 
}; 

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       thingMaker = new ThingMaker(params); 
       m_map[thingMaker] = std::thread(function_ptr, thingMaker); 
      } break; 
      case 't': // termination event trigger 
      { 
       m_map[thingMaker].second.join(); 
       m_map.erase(thingMaker); 
       delete thingMaker; 
      } break; 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

因爲這顯然是不完整的代碼,你必須調整上面的代碼,以滿足您的需求,但你可以在模板中交換地圖的鍵/值,或者使用線程ID代替,如果這樣會更有意義的話(例如std::map<std::thread::id, ThingMaker*>等),但是像map這樣的東西可以避免迭代遍歷每個線程上的數組和join如果你不一定需要一個實現一個完整的線程池實現。

注意事項:使用detach並不差,其實它相當有用;將線程信號分離到內核,一旦線程完成執行(它釋放某些資源和句柄),就可以「清理」線程。當你知道你不再需要訪問底層線程句柄時(比如在一個非常短暫的線程中),在線程上調用detach是很有用的。它既不壞也不好,只是一個利用的工具(如臭名昭着的goto聲明)。

希望能有所幫助。

+0

真棒回答。很棒。謝謝你對'detach'的澄清。 –

相關問題