2015-05-20 38 views
2

我有一個C++插件,它是爲一個專用軟件編寫的,該軟件對稱爲OpenLibrary的函數進行異步調用。要知道圖書館加載何時完成,我必須註冊一個特定事件。然後,當該事件被觸發時,將調用一個OnEvent例程。由於專有原因,這種邏輯有點消毒,但異步調用和onEvent觸發器正常工作。不幸的是,由於OpenLibrary調用是異步的,因此循環不會被阻塞,並且會繼續等待EVENT_LIBRARY_LOADED事件。我需要連續處理文件。爲現有異步代碼創建C++阻塞函數

... 

void MyApp::main() 
{ 
    for(int i=0; i<total; ++i) { 
     pData->RegisterEvent(EVENT_LIBRARY_LOADED, this); 
     pData->OpenLibrary("c:/path/file.dat"); // asynchronous call 
    } 
} 

... 


void MyApp::OnEvent(ID eventType) 
{ 
    if (eventType == EVENT_LIBRARY_LOADED) { 
     qDebug() << "Library load has completed"; 
    } 
} 

... 

該插件需要VS2008,並且還利用了Qt庫。

我想創建一個名爲waitForEvent的函數,其中後續代碼被阻塞,直到事件發生,然後waitForEvent可以將控制返回到調用例程循環。這樣,我可以留在我的主要例程循環中,只需等待事件再繼續。任何建議感激。

更新:我已經嘗試了以下兩種極好的建議,但在任何情況下,我都會得到相同的結果。 WaitForSingleObject或condition_variable.wait BOTH防止EVENT_LIBRARY_LOADED事件觸發OnEvent函數被調用,從而凍結循環。

其他建議讚賞。

+0

使用互斥鎖和條件變量? –

+0

這是我的理解是一個條件變量只在vC++ 11中可用?我在這方面做了許多嘗試,但由於經驗不足,我沒有得到任何地方。 – panofish

+0

@panofish如果你真的必須堅持舊版本的C++,可以使用[boost庫](http://www.boost.org/) - 它提供了互斥和條件變量。或者,您可以實施[Peterson算法](http://en.wikipedia.org/wiki/Peterson's_algorithm)或任何其他[互斥](http://en.wikipedia.org/wiki/Mutual_exclusion)算法 –

回答

2

如果Boost庫是一個選項,使用boost::conditional_variable

你已經說得很清楚C++ 11不是一個選項(否則,您可以使用std::conditional_variable)。 boost::conditional_variable將完成您需要做的事情,而且使用起來非常簡單。你只需要調用waitnotify_one

void MyApp::main() 
{ 
    for(int i=0; i<total; ++i) { 
     pData->RegisterEvent(EVENT_LIBRARY_LOADED, this); 
     pData->OpenLibrary("c:/path/file.dat"); // asynchronous call 
     conditional_variable.wait(); // wait until we've been signaled 
    } 
} 

void MyApp::OnEvent(ID eventType) 
{ 
    if (eventType == EVENT_LIBRARY_LOADED) { 
     qDebug() << "Library load has completed"; 
     // signal completion: 
     conditional_variable.notify_one(); 
    } 
} 

否則,你可以使用Windows Event objects

這些工作非常類似於上面,而是多了幾分複雜的使用(也OS專用)。

HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); 
void MyApp::main() 
{ 
    for(int i=0; i<total; ++i) { 
     // Prepare signal (otherwise if the signal has been Set already, Wait will return instantly) 
     ::ResetEvent(hEvent); 
     pData->RegisterEvent(EVENT_LIBRARY_LOADED, this); 
     pData->OpenLibrary("c:/path/file.dat"); // asynchronous call 
     // wait for event to signal: 
     ::WaitForSingleObject(hEvent, INFINITE); 
    } 
} 

void MyApp::OnEvent(ID eventType) 
{ 
    if (eventType == EVENT_LIBRARY_LOADED) { 
     qDebug() << "Library load has completed"; 
     // Signal event: 
     ::SetEvent(hEvent); 
    } 
} 
+0

這看起來非常有希望......給我一些時間來吸收和實施...我會在明天的某個時候做出迴應。謝謝。 :) – panofish

+0

我實現了Windows事件對象解決方案,但奇怪的事情正在發生。 WaitForSingleObject調用阻止OnEvent被觸發,所以循環永久停留在WaitForSingleObject !?沒有WaitForSingleObject,OnEvent就會被觸發。 – panofish

+0

我也嘗試了boost :: conditional_variable的第一個建議,並得到了與「Windows事件對象」相同的結果。 conditional_variable.wait()命令阻塞了EVENT_LIBRARY_LOADED並且OnEvent函數永遠不會被調用...所以程序循環凍結了!任何更多的想法非常感謝。 – panofish