내 FileWatcher
클래스의 단위 테스트를 작성하려고합니다.대기 WaitingForMultipleObjects
FileWatcher
는 Thread 클래스에서 파생와 스레드 프로 시저에서 두 개의 손잡이를 기다려야 WaitForMultipleObjects
을 사용
- 핸들이 저 위의 대기를 취소 할 수 있도록하는 이벤트에 대한
FindFirstChangeNotification
- 핸들에서 돌아왔다.
따라서 기본적으로 FileWatcher
이 무엇이든 기다리고 있습니다. 파일을 변경하거나 시청을 중지하라고합니다.
이제이 클래스를 테스트하는 코드를 작성하려고 할 때 대기가 시작될 때까지 기다려야합니다.
Peusdo 코드 :
FileWatcher.Wait(INFINITE)
ChangeFile()
// Verify that FileWatcher works (with some other event - unimportant...)
문제는 경쟁 조건이 있다는 것입니다. FileWatcher가 라인 # 2에서 파일 변경을 트리거하기 전에 대기 (즉, 해당 스레드가 WaitForMultipleObjects
에서 차단됨)를 시작했는지 확인해야합니다. 나는 잠자기를 사용하고 싶지 않습니다. 왜냐하면 해키처럼 보이고 디버깅 할 때 문제가 생길 수 있기 때문입니다.
내가 SignalObjectAndWait
잘 알고 있어요,하지만 난에 "SignalObjectAndWaitOnMultipleObjects을"을 필요로하기 때문에 정말, 내 문제가 해결되지 않는 ...
어떤 아이디어가?
// 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
에서 상속 및 스레드 기능을 구현하고, 다음과 같은 :
편집
비트를 명확히하기 위해, 여기에 FileWatcher
클래스의 단순화 된 버전입니다 (매우 단순화 됨) :
_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;
스레드 함수는 두 개의 핸들, 즉 변경 알림 및 다른 하나 인 "스레드 중지"이벤트 (스레드에서 상속)에서 대기합니다.
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_을 의미합니까? 그러나 이벤트로 변경 핸들을 만드는 것을 드러내지 않는이 클래스의 경우에는 그렇지 않습니다. 아니면 내가 너를 오해했을 수도 .. –
하지만 다른 방법은 없습니다. 이것을 구현하는 표준 방법은 기다려야 할 객체를 열고 (당신의 경우 파일 감시자를 생성하고 시작) 다른 객체에게 신호를 보낸 다음 첫 번째 객체를 기다리는 것입니다. 그것이 완료된 방법이며,이를 위해 클래스 디자인을 변경해야합니다. – wj32
'FileWatcher'의 생성자에서 FindFirstChangeNotification을 호출하지 않습니까? 그 순간부터 디렉토리를 감시해야합니다. 아마도 더 많은 코드를 게시하여 정확히 무엇이 진행되고 있는지 알 수 있습니다. – avakar