2015-04-21 89 views
0

我從一個UI事件(單獨的類)開始一個工作線程(寫在一個新的類中)。現在,當新的工作線程從主UI線程創建時,它立即從控件返回,這導致工作線程類對象被銷燬。通過檢查下面的代碼可以找到更好的解釋。C++多線程對象超出範圍

//class - UI 
void CUIClass::button_click() 
{ 
    CDataProcess obj; 
    obj.Start(); 
} 

//class - DataProcess 
CDataProcess::CDataProcess() 
{ 
} 

CDataProcess::~CDataProcess() 
{ 
} 

void CDataProcess::Start() 
{ 
    CWinThread *pThread = AfxBeginThread(DataProcessingThread, this); 
} 

UINT CDataProcess::DataProcessingThread() 
{ 
    //some processing 
} 

現在的一些可能的解決方案我想到的是:

  • 使 'CDataProcess OBJ;'一個UI類的成員,所以它不會超出範圍。但我有目的地保留它。
  • 在UI類button_event()中使用WaitForSignleObject來等待工作線程完成信號或在工作類中寫入等待函數。

還有什麼是正確的解決方案?

+0

確保CDataProcess實例超出線程是您的責任。把它作爲局部變量是沒有意義的。無論您在「保持本地」時想到什麼目的,您都必須重新考慮。阻塞UI線程,直到工作線程完成完全失敗了讓工作線程放在第一位的目的;如果你願意這樣做(並讓UI凍結),只需在UI線程上做同樣的工作就可以開始。 –

+0

您可以使用':: WaitForSingleObject(pThread-> m_hThread,INFINITE);'在主線程中等待您的工作線程。 – gomons

+0

OT:除非你需要MFC中特定的東西,否則你總是可以使用['std :: thread'](http://en.cppreference.com/w/cpp/thread/thread)VS2013支持 – Mgetz

回答

1

那麼,如果您打算爲按鈕上的每次單擊打開一個線程(我認爲您需要重新考慮),則線程池在這裏最適合。

基本上,您希望將onClick邏輯寫入一個函數(可以調用其他函數和對象,肯定會),這將成爲onClick事件的回調函數。那麼你可以讓你的線程池執行異步回調。

您可能還想了解有關std::async的啓動函數,它可以啓動異步函數,但請記住,如果線程很重,您可能想要使用線程池。

+0

那麼,多線程將不會被創建。這只是一個樣本。 – hypheni

+0

然後使線程成爲按鈕的成員變量,或者更好地創建一個管理線程的類,並且按鈕將包含它。 –

-1

這取決於你想要達到的目標。 Obviousely,你需要創建一個比button_click回調生活不再是一個工人對象:

CDataProcess* obj = new CDataProcess(); 
obj->Start(); 

假設按名稱AfxBeginThread,你是在Windows(更具體的,MFC)環境。你可以使用任何「任務池」技術(再次,取決於你想要達到的目標)。連接點,線程池 - 你的名字。您需要如何檢測任務完成時的情況?如何將其展示給用戶?你會允許用戶取消任務嗎?等等等等。

+0

然後該函數結束,obj超出範圍,並且您有內存泄漏。除了不能以任何方式終止創建的線程 –

+0

肯定你必須進一步跟蹤這個對象。怎麼樣?基本上取決於你的線程模型。 我不能推薦,但你可以做的是 刪除這個 總而言之,如果你需要一個比{}作用域壽命更長的對象,則由你來管理它。 – rezdm

+0

你永遠不會'刪除這個'!這是一個危險的做法! –

0

嗯,我想我已經給我造成了一些嚴重的麻煩。我應該堅持DataProcess功能在一個可以從UI類啓動的線程調用的獨立類中。這樣它解決了每一個問題。