WaitForMultipleObjects的使用问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WaitForMultipleObjects的使用问题相关的知识,希望对你有一定的参考价值。
小弟目前已经编译好一个程序load.exe,需要在指定的文件夹下面寻找指定的DLL文件,然后分别启动多个load.exe的子进程加载这些DLL文件,我用CreateProcess创建了各个子进程后再用WaitForMultipleObjects对这些进程等待,若是某一子进程崩溃就重新CreateProcess创建一个相同的进程。下面是我写的大概的代码,但在编译运行的时候发现WaitForMultipleObjects返回值是-1,除此之外也创建的进程也不断崩溃,通过while循环又不断新创建,不知道问题出来哪里啊……
请各位大虾指点指点,感觉万分
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
ZeroMemory( &sInfo, sizeof(sInfo));
ZeroMemory( &pInfo, sizeof(pInfo));
sInfo.cb = sizeof(sInfo);
sInfo.dwFlags = STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_SHOWNORMAL;
WIN32_FIND_DATA FindFileData;
char foldName[128] = "c:\\DLL\\acb*.dll";//在指定文件夹寻找文件,并以文件名作为需要启动函数的参数
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile( foldName, &FindFileData );//找出文件夹下第一个符合条件的文件
if(hFind == INVALID_HANDLE_VALUE)
printf("Invalid file handle.\n");
FindClose(hFind);
return -1;
char *proName = "E:\\load.exe";//需要启动的程序
Handle pHandles[64];
char cmdLine[64][128];
int nCount=0;
strcpy(cmdLine[nCount],FindFileData.cFileName);
if( !CreateProcess(proName, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo))
printf("Run load.exe failed!\n");
return 0;
pHandles[nCount]=pInfo.hProcess;
nCount++;
while( FindNextFile( hFind, &FindFileData )!=0 )
strcpy(cmdLine[nCount],FindFileData.cFileName);
if( !CreateProcess(proName, cmdLine[nCount], NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo))
printf("Run load.exe failed!\n");
return 0;
pHandles[nCount]=pInfo.hProcess;
nCount++;
FindClose( hFind );
DOUBLE dwRet=0;
DOUBLE dwRet=nIndex;
while(1)
dwRet=WaitForMultipleObjects( nCount,pHandles,false,INFINITE);//等待多个进程
nIndex = dwRet - WAIT_OBJECT_0;
CreateProcess( proName, cmdLine[nIndex], NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo );
分值用完了,还是希望你们能发挥互相帮助的传统
等待 WaitForMultipleObjects
【中文标题】等待 WaitForMultipleObjects【英文标题】:Waiting on WaitForMultipleObjects 【发布时间】:2010-01-10 17:42:11 【问题描述】:我正在尝试为我的 FileWatcher
类编写单元测试。
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();
;
And 从 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);
这个想法是摆脱中间的睡眠。
【问题讨论】:
【参考方案1】:没有比赛,您不必等待FileWatcher
输入WaitForMultipleObjects
。如果您在调用函数之前执行更改,它将立即返回。
编辑:我现在可以看到比赛了。为什么不移动以下行
_changeEvent = ::FindFirstChangeNotificationW(/*...*/);
从线程函数到FileChangeWatcher
的构造函数?这样,您可以确定在调用 StringToFile
函数时,该文件已被监视。
【讨论】:
您的意思是我可以在调用 Wait 之前更改文件,但 在 创建更改通知句柄之后?但这个类的情况并非如此,它不会将更改句柄的创建作为事件公开。或者也许我误解了你.. 但是没有其他方法可以做到这一点。实现这一点的标准方法是打开要等待的对象(在您的情况下创建文件观察程序并启动它),向另一个对象发出信号,然后等待第一个对象。这就是它的完成方式,你需要改变你的类设计以适应这种情况。 你不是在FileWatcher
的构造函数中调用FindFirstChangeNotification吗?从那一刻起,该目录应该受到关注。也许您可以发布更多代码,以便我们知道到底发生了什么。
我没有从构造函数调用 FFCN。但是现在我正在尝试这样做,但我仍然遇到了比赛条件。当我让它在没有断点的情况下运行时,文件更改对于观察者来说很快就会发生并且它会永远等待。当我在更改文件之前在单元测试代码中放置一些断点,然后让它在点击它之后继续运行时,一切正常(延迟就足够了)。
划掉最后一条评论。其他一些错误(在上面的代码中不可见)导致它卡住了。将其移至构造函数确实可以解决问题。【参考方案2】:
您应该在观察者的构造函数中调用FindFirstChangeNotification()
并存储它返回的句柄以在您的线程函数中使用。这意味着您将从构建的那一刻起就捕捉到变化事件。
一旦您的线程启动,它只需在两个句柄上调用 wait 即可。如果在线程启动之前发生了更改,那么FindFirstChangeNotification()
返回的句柄将已经发出信号并且更改将被处理。如果您希望线程监控许多更改,那么它应该在处理每个通知后循环并调用FindNextChangeNotification()
。
【讨论】:
【参考方案3】:你可以使用互斥锁吗?在一个线程可以访问它想要的资源之前,它必须锁定 Mutex 并为其他需要该资源的线程解锁它。
【讨论】:
你指的是什么资源?在这种情况下,您如何建议我使用互斥锁?【参考方案4】:调用 CreateEvent() 来创建一个无信号事件。当观察者线程进入其主循环(或其他)时,SetEvent()。同时,在 FileWatcher 中首先 WaitForSingleObject() 事件,然后一旦返回,WFMO 就像你之前做的那样。
【讨论】:
但这会产生另一种竞争条件。以上是关于WaitForMultipleObjects的使用问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ 中使用 waitformultipleobjects
WaitHandle.WaitAny 匹配 WaitForMultipleObjects 功能
win32 - WaitForMultipleObjects的使用