为现有的异步代码Windows事件对象创建C ++阻止功能

问题描述 投票:2回答:1

我有一个为专有软件编写的C ++插件,该插件对名为OpenLibrary的函数进行异步调用。要知道库加载何时完成,我必须注册一个特定的事件。然后,当触发该事件时,将调用OnEvent例程。出于专有原因,此逻辑已经过灭菌,但是异步调用和onEvent触发器可以正常工作。不幸的是,由于OpenLibrary调用是异步的,因此该循环不会被阻塞并且不会等待EVENT_LIBRARY_LOADED事件而继续。我需要按顺序处理文件。

...

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可以将控制权返回给调用例程循环。这样,我可以停留在主例程循环中,只需等待事件再继续即可。任何建议表示赞赏。

更新:我在Tas的下面尝试了两个很好的建议,但是无论哪种情况,我都得到相同的结果。 WaitForSingleObject或condition_variable.wait两者都阻止EVENT_LIBRARY_LOADED事件触发调用OnEvent函数,从而冻结了循环。

感谢其他建议。

c++ asynchronous
1个回答
2
投票

如果可以选择增强库,请使用boost::condition_variable

您已经明确指出C ++ 11不是选项(否则您可以使用std::condition_variable)。 boost::condition_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
        condition_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:
        condition_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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.