C#从CancellationToken.Register内部抛出操作CanceledException
我有一个长时间运行的操作,我想在5秒后取消。不幸的是,IsCancellationRequested的轮询是不可能的(说来话长) 我使用下面的代码在取消回调中抛出OperationCanceledException。我想在主线程中捕获异常并进行处理,以便完全退出应用程序 这似乎无法正常工作,因为这会导致未处理的异常,并且应用程序不会正常终止 感谢您的帮助。谢谢C#从CancellationToken.Register内部抛出操作CanceledException,c#,.net,multithreading,cancellation,C#,.net,Multithreading,Cancellation,我有一个长时间运行的操作,我想在5秒后取消。不幸的是,IsCancellationRequested的轮询是不可能的(说来话长) 我使用下面的代码在取消回调中抛出OperationCanceledException。我想在主线程中捕获异常并进行处理,以便完全退出应用程序 这似乎无法正常工作,因为这会导致未处理的异常,并且应用程序不会正常终止 感谢您的帮助。谢谢 void TestTimeOut() { var cts = new CancellationToken
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
}
}
您正在捕获一个
aggregateeexception
,但实际上抛出了一个OperationCanceledException
,该异常将不会被捕获
更改以捕获所有类型的异常,例如
catch (Exception ex) { ... }
解决 您的代码中有很多禁忌,但我猜您只是将其用作解决问题的演示。 解决方案是
TaskCompletionSource
,我的演示也很难看,Task.Run()的层次太多,如果使用异步,应该一直异步。所以不要在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();
}
静态void LongRunningOperation(CancellationToken令牌)
{
TaskCompletionSource tcs1=新的TaskCompletionSource();
token.Register(()=>{tcs1.trysetconceled(token);});
Task.Run(()=>
{
//长期运行的操作在这里
睡眠(10000);
tcs1.TrySetResult(0);
},代币);
tcs1.Task.Wait();
}
如果你等待()
它,那么在任务中运行它有什么意义?CancellationToken
的使用是合作的。如果您没有实际使用异步功能(Wait关键字),也许您可以创建一个线程。@DennisKuypers Task.Wait()之后还需要做其他事情,但前提是长时间运行的任务完成。否则,我希望捕获已取消的异常,进行一些整理并退出应用程序。我的观点是-如果您正在使用Task.Wait()
进行阻止,为什么还要麻烦将其放在其他线程上?如果在后台线程上运行长时间运行的东西+阻塞调用线程与只在调用线程上运行工作没有区别thread@DennisKuypers因为我需要任务超时,所以我使用了CancelAfter。我确实尝试过异步/等待。。。但这里的主要问题是如何从任务中正确抛出OperationCanceledException。您能否提供有关长时间运行的操作的更多信息?也许可以将取消添加到它中(或者它提供了一种实际中止操作的机制)。感觉问题应该是关于手术以及如何正确地阻止它而不是杀死它。