0

我注意到 AutoResetEvent 在 WaitOne() 调用中间时(有时)完全冻结了消息循环,甚至有效地阻止了信号消息。

IE:

  1. (UI) 新线程产生
  2. (UI) 代码调用 WaitOne(); 超时:10s
  3. (T2) 线程打开设备,调用 Set()
  4. (UI) WaitOne 阻塞消息循环
  5. (UI) WaitOne 超时,代码继续执行
  6. (UI) 主窗口接收信号并继续(但 WaitOne 失败)

有任何想法吗?

编辑:添加 UI/T2 来指定线程。另外,我正在尝试将第 3 方库变为同步。打开设备涉及一个 Open() 调用,该调用反过来会产生一个 OpenOK 或 OpenFailed 事件,我正在尝试进行一个 bool Open() 调用,该调用根据产生的事件返回真/假。

4

3 回答 3

1

...有效地甚至阻止信号消息。

您不能“阻止信号”发送,只能阻止其他线程到达设置事件的地步。等待句柄根本不需要消息泵。

我唯一能想到的可能是有问题的 COM 对象与 UI 线程相关联。访问 COM 对象可能会尝试从 T2 调用回等待 T2 执行某些操作的 UI 线程(死锁)。要查看这是否确实是问题,请确保您没有在 UI 线程上创建或访问 COM 对象。

于 2009-09-29T02:41:33.860 回答
0

这是竞争条件的结果。问题是第 3 步可能发生在第 2 步之前,因为它们位于不同的线程上。因为您使用的是 AutoResetEvent,所以在调用 WaitOne 时,该事件已被重置。

由于这个问题,只要有可能,我通常会尽量避免使用 AutoResetEvents 来支持 ManualResetEvents。

ManualResetEvent 的事件顺序是(我已将事件 2 列为 2a 和 2b 以证明它们的操作顺序无法保证):

  1. 新线程产生
  2. 一种。原始线程调用 WaitOne(); 湾。新线程调用 Set();
  3. 原始线程唤醒。
  4. 原线程调用 Reset();
于 2009-09-28T23:52:57.087 回答
0

您可能会在“Waiting on the mainthread while continue to process”上找到这篇SO 帖子,还可以从 MSDN
签出Calling Synchronous Methods Asynchronously

于 2009-09-29T01:19:52.123 回答