代码之家  ›  专栏  ›  技术社区  ›  Samuel Neff

为什么等待manualReseteEvent的线程会继续等待,即使调用了close()?

  •  6
  • Samuel Neff  · 技术社区  · 15 年前

    今天我们很惊讶地发现线程在等待 ManualResetEvent 即使事件已关闭,也要继续等待。我们本可以预料到 Close() 将隐式地向等待的线程发出信号。

    我们跟踪到这一点是因为我们的一些Windows服务没有像我们希望的那样快速关闭。我们正在改变我们所有的 Dispose 关闭的实现 手动储液阀 调用的引用 Set 第一。

    有人能解释为什么吗 Close 不隐式调用 设置 ?您希望等待线程何时继续等待?

    下面是我们的测试代码,演示我们的发现:

        private static readonly Stopwatch _timer = Stopwatch.StartNew();
    
        public static void Test()
        {
    
            var sync = new ManualResetEvent(false);
    
            ThreadPool.QueueUserWorkItem(state =>
                                             {
                                                 Log("ThreadPool enter, waiting 250ms...");
                                                 sync.WaitOne(250);
                                                 Log("ThreadPool exit");
                                             });
    
            Log("Main sleeping 100");
            Thread.Sleep(100);
            Log("Main about to close");
            // sync.Set();      // Is Set called implicitly?  No...
            sync.Close();
    
            Log("Main waiting for exit 500ms");
            Thread.Sleep(500);
        }
    
        private static void Log(string text)
        {
            Console.WriteLine("{0:0} {1}", _timer.ElapsedMilliseconds, text);  
        }
    

    当我们用 集合 呼叫已评论,我们收到…

    0 Main sleeping 100
    0 ThreadPool enter, waiting 250ms...
    103 Main about to close
    103 Main waiting for exit 500ms
    259 ThreadPool exit
    

    当我们明确呼叫 集合 我们得到这个…

    0 Main sleeping 100
    0 ThreadPool enter, waiting 250ms...
    98 Main about to close
    98 ThreadPool exit
    98 Main waiting for exit 500ms
    
    2 回复  |  直到 15 年前
        1
  •  2
  •   Adam Robinson    15 年前

    Close 是处理对象的方法( 关闭 Dispose 在这个类上产生相同的行为)。它不会影响句柄的状态。假设在所有情况下,用户都希望在我关闭的句柄上等待线程继续,这似乎不合理。事实上,手柄是 在使用中 应该表明你不应该打电话 关闭 首先。

    这不是“为什么不应该”的问题 Set 是否隐式调用?”这是一个概念上的问题:如果你打电话给 关闭 , 你不应该再关心这个东西了 . 使用 集合 Reset 控制线程之间的执行流;不要调用 关闭 (或) 处置 )在任何物体上, WaitHandle 包括,直到它们不再使用。

        2
  •  1
  •   Kimi    15 年前

    这些同步事件基于Win32等待句柄,并且 Close() 方法只释放它们(例如 Dispose() )没有信号,等待线程继续等待。