我正在开展一个涉及两个流程的项目,让他们成为A和B. A有两个线程:T1和T2。
A和B分开运行。
在某个时刻,T1向B发送一条消息(它是一个COM调用,一个搜索请求)。当B处理了一些数据时,它通过直接发送结果(再次,它是一个COM调用,搜索结果)返回T2。 我需要T1来阻止,直到T2处理了B的数据。 到目前为止,我使用了以下解决方案:
初始化:
searchSyncSempahore = ::CreateSemaphore(NULL, 0, 1, NULL);
T1:
B_handle->search(searchString);
::WaitForSingleObject(searchSyncSempahore, INFINITE);
// Use searchResult variable
T2:
searchResult = _some_data_from_B;
::ReleaseSemaphore(searchSyncSempahore, 1, NULL);
到目前为止这是有效的。即使B非常快,T2在调用WaitForSingleObject行之前调用ReleaseSemaphore也能正常工作。
我的问题是:如果B崩溃会发生什么? T1将永远等待。我必须指定超时,但如果T2收到结果时它太低了,它只会搞砸信号量,弄乱后面的搜索。
那么我怎样才能正确地同步这两个线程,同时考虑到T2永远不会被调用(即如何实现“中止搜索”)?
答案 0 :(得分:3)
可能的解决方案是创建一个监视程序线程,该线程将使用Manual-Reset events处理此类情况。所以逻辑会改变一小部分:而不是等待互斥体,你可以等待事件。看门狗线程可以检查线程是否卡住了很长时间,只是自己设置事件并且可以设置一个额外的事件,说明出现了危急情况。 我的意思是这个第三个线程可以作为看门狗定时器。
另一种变体是在第三个帖子中使用 Condition Variables 。所以,你可以简单地踢一个条件变量,它会唤醒等待它的线程。我必须承认,我对这种方法并不是很熟悉。
<强>更新强>: 考虑使用SignalObjectAndWait函数。该函数发出一个对象的信号,并作为单个操作等待另一个对象。此外,您可以设置等待超时,并且如果间隔过去,函数将返回,即使对象的状态是无信号的。
使用线程监视程序的另一个好处是,您可以在其中执行其他操作:记录到文件甚至在MS EventLog中,或者可以提供更改应用程序行为的逻辑。另一个例子是监视程序线程可以实现“线程冗余”功能。
答案 1 :(得分:2)
比显式监视程序更简单的方法可能是等待进程句柄。
Windows等待函数可以等待几乎所有的句柄(文件,套接字,线程,进程,事件......)。因此,使用WaitForMultipleObjects
并将两个您的信号量和进程句柄(或主线程句柄)放入等待集。如果信号量发出信号或进程终止(无论出于何种原因),则wait函数应相应返回。
您可以区分导致wait函数从返回值返回的对象(应该是WAIT_OBJECT_0
或WAIT_OBJECT_0 + 1
)。如果在之前已经发生崩溃你调用了wait函数,则句柄无效,在这种情况下,wait函数应该返回WAIT_FAILED
,这是应该检查的另一个条件。