我需要为函数调用设置超时,以便向ui发送反馈。
Task.Factory.StartNew(() => {
var task = Task.Factory.StartNew(() => {
lock(this) {
// do work
Thread.Sleep(5000);
}
});
// if the lock above blocks the thread, this might be timed out
if(task.Wait(timeout)) {
// done
} else {
// timeout
}
});
我的初步解决方案是我将锁定置于内部任务之外
Task.Factory.StartNew(() => {
Monitor.Enter(obj);
var task = Task.Factory.StartNew(() => {
// do work
Thread.Sleep(5000);
Monitor.Exit(obj);
});
// if the lock above blocks the thread, task won't start.
if(task.Wait(timeout)) {
// done
} else {
// timeout
}
});
但它没有用。
我的问题是,如何为我的任务指定超时但排除锁定等待?
答案 0 :(得分:0)
您可以使用SemaphoreSlim
进行异步等待。此外,一旦你这样做,你将不需要外部Task.Run
,但我把它留在了。你可以使用Task.Delay
而不是Thread.Sleep
,因为前者不阻止当前线程,异步等待,也可以通过CancellationToken
取消。
private SemaphoreSlim semaphore = new SemaphoreSlim(1,1);
// Add ability to cancel work
public async Task DoWorkAsync(Action work, CancellationToken token)
{
await Task.Run(async () =>
{
try
{
await semaphore.WaitAsync(token);
await Task.Run(work, token);
}
finally
{
semaphore.Release();
}
// use await Task.Delay rather than Thread.Sleep as it doesn't use a thread
// and stops almost immediately when cancellation requested.
await Task.Delay(5000, token);
}, token);
}
要创建超时情节,请创建一个超时的CancellationTokenSource
并抓住OperationCanceledException
以观察超时。
try
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
await DoWorkAsync(() => /*do work*/, cts.Token);
}
catch(OperationCanceledException ex)
{
Console.WriteLine("Operation timed out");
}