我正在尝试为我的FileWatcher
类写一个单元测试。Waiting on WaitForMultipleObjects
FileWatcher
从Thread类派生,并使用WaitForMultipleObjects
等待它的线程过程中两个手柄:
- 手柄从
FindFirstChangeNotification
- 句柄返回事件,让我取消上述等待。
因此,基本上FileWatcher
正在等待先发生的任何事情:文件更改或我告诉它停止观看。
现在,当试图编写测试这个类的代码时,我需要等待它开始等待。
Peusdo代码:
FileWatcher.Wait(INFINITE)
ChangeFile()
// Verify that FileWatcher works (with some other event - unimportant...)
问题是,有一个竞争条件。我需要先确保FileWatcher已经开始等待(即其线程现在被阻止在WaitForMultipleObjects
上),然后才能触发第2行中的文件更改。我不想使用Sleeps,因为,它看起来很拙劣,并且在调试时会给我带来麻烦。
我熟悉SignalObjectAndWait
,但它并没有真正解决我的问题,因为我需要它“SignalObjectAndWaitOnMultipleObjects” ......
任何想法?
编辑
要澄清一点,这里的FileWatcher
类的简化版本:
// 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
继承并实现线程函数,它看起来是这样的(非常简化):
_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;
请注意,线程函数在两个句柄上等待,一个 - 更改通知,另一个 - “停止线程”事件(从Thread继承)。
现在测试这个类的代码如下所示:
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的测试调用:
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);
的想法是在中路摆脱睡眠。
你的意思是我可以在调用Wait之前更改文件,但_after_创建更改通知句柄?但是对于这个类来说并不是这样,它不会将创建更改句柄作为事件公开。或者,也许我误解了你.. – 2010-01-10 18:19:06
但是没有其他办法可以做到这一点。实现这个的标准方法是打开要等待的对象(在您的情况下创建文件观察器并启动它),发出其他对象的信号,然后等待第一个对象。这就是它的做法,你需要改变你的课程设计来适应这个。 – wj32 2010-01-10 18:40:04
你不是在'FileWatcher'的构造函数中调用FindFirstChangeNotification吗?该目录应该从那一刻开始观察。也许你可以发布更多的代码,以便我们知道究竟发生了什么。 – avakar 2010-01-10 18:44:15