我需要一种方法来同步执行一些操作,这应该在半秒内完成,但可能只是暂停几分钟。如果它超时我不关心结果。这是我现在正在使用编译器生成的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()
会爆炸。
答案 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
看了一些代码示例,我看到它返回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
的一个实例,当我的异步调用完成时,它会自动从线程池线程中释放出来。