3

我正在做一个涉及两个进程的项目,让它们成为 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 在 T1 到达 WaitForSingleObject 行之前调用 ReleaseSemaphore,它也可以工作。

我的问题是:如果 B 崩溃会发生什么?T1 将永远等待。我必须指定超时时间,但如果 T2 收到结果时它太低,它只会搞砸信号量,弄乱下面的搜索。

那么考虑到 T2 永远不会被调用(即如何实现“中止搜索”),我如何正确同步这两个线程?

4

2 回答 2

3

可能的解决方案是创建一个看门狗线程,该线程将使用手动重置事件来处理这种情况。所以逻辑会改变一点:你可以等待事件,而不是等待互斥体。看门狗线程可以检查线程是否卡住了很长时间,只是自己设置事件,并且可以设置一个额外的事件来说明出现了危急情况。我的意思是这第三个线程可以充当看门狗计时器

另一种变体是在第三个线程中使用条件变量。因此,您可以简单地启动条件变量之一,它会唤醒等待它的线程。我必须承认,我对这种方法不是很熟悉。

更新:考虑使用SignalObjectAndWait函数。该函数向一个对象发出信号并作为单个操作等待另一个对象。此外,您可以设置等待超时,如果时间间隔过去,即使对象的状态是非信号状态,该函数也会返回。

使用线程看门狗的另一个好处是,您可以在其中执行其他操作:记录到文件甚至 MS EventLog 中,或者可以提供更改应用程序行为的逻辑。另一个例子是看门狗线程可以实现“线程冗余”功能。

于 2012-06-14T10:14:35.320 回答
2

比显式看门狗更简单的方法可能是等待进程句柄。

Windows 等待函数可以等待几乎所有作为句柄的东西(文件、套接字、线程、进程、事件……)。

因此,使用信号WaitForMultipleObjects量和进程句柄(或主线程句柄)并将其放入等待集中。如果信号量发出信号或进程终止(无论出于何种原因),则等待函数应相应返回。

您可以从返回值中区分是哪个对象导致等待函数返回(应该是WAIT_OBJECT_0WAIT_OBJECT_0 + 1)。如果在您调用等待函数之前已经发生崩溃,则句柄无效,在这种情况下,等待函数应该返回WAIT_FAILED,所以这是另一个应该检查的条件。

于 2012-06-14T11:26:47.640 回答