更好的超时检测同步操作

时间:2010-05-28 15:13:58

标签: c# timeout threadpool synchronous begininvoke

我需要一种方法来同步执行一些操作,这应该在半秒内完成,但可能只是暂停几分钟。如果它超时我不关心结果。这是我现在正在使用编译器生成的delegate.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 个答案:

答案 0 :(得分:4)

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

在.NET 4.0中,我将看一下Task Parallel Library,它位于System.Threading程序集中,是4.0的新功能。

具体来说,请查看Task class以及Wait method,以便您指定超时。

此外,您还需要了解cancel a Task如何超时。

答案 1 :(得分:2)

呃,现在我使用编译器生成的delegate.BeginInvoke看了一些代码示例,我看到它返回IAsyncResultAsyncWaitHandle完全符合我的目标:

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的一个实例,当我的异步调用完成时,它会自动从线程池线程中释放出来。