[英]C# Throw OperationCanceledException from inside CancellationToken.Register
我有一個長時間運行的操作,想在5秒后取消。 不幸的是,不可能對IsCancellationRequested進行輪詢(長話短說)。
我使用下面的代碼在取消回調中引發了OperationCanceledException。 我想在主線程中捕獲異常並進行處理,以便可以完全退出應用程序。
這似乎無法正常工作,因為這會導致未處理的異常,並且應用程序無法正常終止。
任何幫助表示贊賞。 謝謝!
void TestTimeOut()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(5000);
try
{
var task = Task.Run(() => LongRunningOperation(cts.Token));
task.ContinueWith(t => Console.WriteLine("Operation cancelled"), TaskContinuationOptions.OnlyOnFaulted);
task.Wait();
}
catch (AggregateException e)
{
//Handle
}
}
void LongRunningOperation(CancellationToken token)
{
CancellationTokenRegistration registration = token.Register(
() =>
{
throw new OperationCanceledException(token);
});
using (registration)
{
// long running operation here
}
}
您正在捕獲一個AggregateException
但是實際上拋出了一個OperationCanceledException
,它將不會被捕獲。
進行更改以捕獲所有類型的異常,例如
catch (Exception ex) { ... }
解決。
您的代碼有很多No-No-es,但我想您只是將它用作問題演示。 解決方案是TaskCompletionSource
,我的演示也很丑陋,太多的Task.Run()層,如果使用Async,則應該一直異步。 因此,不要在PRD中使用它,自己研究TaskCompletionSource
並找出更好的解決方案。
static void LongRunningOperation(CancellationToken token)
{
TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
token.Register(() => { tcs1.TrySetCanceled(token); });
Task.Run(() =>
{
// long running operation here
Thread.Sleep(10000);
tcs1.TrySetResult(0);
}, token);
tcs1.Task.Wait();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.