4

我需要一种同步执行某些操作的方法,该操作应在半秒内完成,但可能只停留几分钟。如果超时,我不在乎结果。这是我现在正在使用编译器生成的委托。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()如果您尝试在已处置的实例上执行此操作,则会爆炸。

4

2 回答 2

4

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

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

具体来说,查看Task 类以及Wait 方法,这将允许您指定超时。

此外,您还需要了解如何在任务超时时取消任务。

于 2010-05-28T15:48:26.670 回答
2

呃,现在我更多地查看了使用编译器生成的代码示例,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是从线程池线程中自动处理的一个实例。

于 2010-05-28T16:13:49.773 回答