首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待WaitForMultipleObjects

等待WaitForMultipleObjects
EN

Stack Overflow用户
提问于 2010-01-10 17:42:11
回答 4查看 1.5K关注 0票数 2

我正试图为我的FileWatcher类编写一个单元测试。

FileWatcher从线程类派生,并在线程过程中使用WaitForMultipleObjects等待两个句柄:

FindFirstChangeNotification

  • A句柄返回的句柄,用于一个允许我取消上述等待.

的事件的句柄

因此,FileWatcher基本上是在等待任何首先发生的事情:文件更改,或者我告诉它停止观看。

现在,当尝试编写测试该类的代码时,我需要等待它开始等待。

Peusdo法典:

代码语言:javascript
复制
FileWatcher.Wait(INFINITE)
ChangeFile()
// Verify that FileWatcher works (with some other event - unimportant...)

问题是有比赛条件。我需要首先确保FileWatcher已经开始等待(即它的线程现在在WaitForMultipleObjects上被阻塞),然后才能触发第2行中的文件更改。我不想使用Sleep,因为它看起来很麻烦,在调试时肯定会给我带来问题。

我熟悉SignalObjectAndWait,但它并不能真正解决我的问题,因为我需要它来“SignalObjectAndWaitOnMultipleObjects”.

有什么想法吗?

编辑

为了澄清一点,下面是FileWatcher类的简化版本:

代码语言:javascript
复制
// Inherit from this class, override OnChange, and call Start() to turn on monitoring. 
class FileChangeWatcher : public Utils::Thread
{
public:
    // File must exist before constructing this instance
    FileChangeWatcher(const std::string& filename);
virtual int Run();
    virtual void OnChange() = 0;
};

它继承了Thread并实现了线程函数,该函数看起来如下(非常简化):

代码语言:javascript
复制
_changeEvent = ::FindFirstChangeNotificationW(wfn.c_str(), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);

HANDLE events[2] = { _changeEvent, m_hStopEvent };

DWORD hWaitDone = WAIT_OBJECT_0;
while (hWaitDone == WAIT_OBJECT_0)
{
    hWaitDone = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);

    if (hWaitDone == WAIT_OBJECT_0)
        OnChange(); 
    else
        return Thread::THREAD_ABORTED;
} 
return THREAD_FINISHED;

注意,线程函数等待两个句柄,一个是更改通知,另一个是“停止线程”事件(继承自线程)。

现在测试该类的代码如下所示:

代码语言:javascript
复制
class TestFileWatcher : public FileChangeWatcher
{
public:
    bool Changed;
    Event evtDone;
    TestFileWatcher(const std::string& fname) : FileChangeWatcher(fname) { Changed = false; }
    virtual void OnChange()
    {
        Changed = true;
        evtDone.Set();
    }
};

并从CPPUnit测试中调用:

代码语言:javascript
复制
std::string tempFile = TempFilePath();
StringToFile("Hello, file", tempFile);
TestFileWatcher tfw(tempFile);
tfw.Start();
::Sleep(100); // Ugly, but we have to wait for monitor to kick in in worker thread
StringToFile("Modify me", tempFile);
tfw.evtDone.Wait(INFINITE);
CPPUNIT_ASSERT(tfw.Changed);

我的想法是摆脱那种处于中间的睡眠状态。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-01-10 17:45:44

没有比赛,你不需要等待FileWatcher进入WaitForMultipleObjects。如果在调用函数之前执行更改,它将立即返回。

编辑:,我现在可以看到比赛了。你为什么不把下面的线移开

代码语言:javascript
复制
_changeEvent = ::FindFirstChangeNotificationW(/*...*/);

从线程函数到FileChangeWatcher的构造函数?这样,您就可以确定在调用StringToFile函数时,文件已经被监视了。

票数 3
EN

Stack Overflow用户

发布于 2010-01-13 11:18:59

您应该在观察者的构造函数中调用FindFirstChangeNotification(),并将它返回的句柄存储在线程函数中。这将意味着,您将捕获从建设的时刻开始的变化事件。

一旦您的线程启动,它只需调用等待两个句柄。如果在线程启动之前发生了更改,那么FindFirstChangeNotification()返回的句柄将被发出信号,并且将处理更改。如果希望线程监视许多更改,那么它应该在处理每个通知之后循环并调用FindNextChangeNotification()

票数 1
EN

Stack Overflow用户

发布于 2010-01-10 18:49:23

你能用Mutex吗?在线程能够访问它想要的资源之前,它必须锁定Mutex并为其他需要该资源的线程解锁它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2037863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档