代码之家  ›  专栏  ›  技术社区  ›  repka

更好的同步操作超时检测

  •  4
  • repka  · 技术社区  · 15 年前

    我需要一种同步执行某些动作的方法,这种方法应该在半秒钟内完成,但可能只需要停留几分钟。如果超时,我不在乎结果。下面是我正在使用编译器生成的委托进行的操作。BeginInvoke:

    static void Main()
    {
        bool disposed = false;
        var wait = new ManualResetEvent(false);
        var a = new Action(
            () =>
                {
                    Thread.Sleep(1000); // <- some looong action
    
                    if (!disposed)
                        lock (wait)
                            if (!disposed)
                                wait.Set();
                });
    
        a.BeginInvoke(a.EndInvoke, null);
    
        bool success = wait.WaitOne(500);
        Console.WriteLine(success ? "success" : "timeout");
    
        lock (wait)
        {
            wait.Dispose();
            disposed = true;
        }
    
        Console.ReadLine();
    }
    

    看起来很难看。我知道lambda关闭 disposed 变量被修改(与我的Resharper不同,我喜欢这个C特性)。因为我想处理 ManualResetEvent . 你能建议在.net4中使用更好的方法吗?也许我应该跳过处理事件并依赖GC吗?

    一个音符: ManualResetEvent.Set() 如果尝试在释放的实例上执行,则会爆炸。

    2 回复  |  直到 15 年前
        1
  •  4
  •   casperOne    15 年前

    不,您不应该跳过对Dispose的调用并依赖GC。这是浪费资源,简单明了。

    在.NET 4.0中,我将查看 Task Parallel Library ,位于System.Threading组件中,是4.0的新组件。

    具体来说,看看 Task class 以及 Wait method ,这将允许您指定超时。

    另外,你还想看看如何 cancel a Task 万一超时了。

        2
  •  2
  •   repka    15 年前

    呃,现在我看了更多使用编译器生成的代码示例 delegate.BeginInvoke 我看到它回来了 IAsyncResult 哪个有 AsyncWaitHandle 完全符合我的目标:

    var a = new Action(() => Thread.Sleep(1000)); // <- some looong action
    IAsyncResult asyncResult = a.BeginInvoke(a.EndInvoke, null);
    bool success = asyncResult.AsyncWaitHandle.WaitOne(500);
    

    万一有 AsyncResult 实际上是 ManualResetEvent 当我的异步调用完成时,它将自动从线程池线程中释放。