C# 取消任务。是否无故延迟或使用异常控制流程?
我不确定对代码中的事件做出反应的两种可能性。我最关心的是哪一个需要更少的资源。 我有一个方法,其中一个观测者注册到C# 取消任务。是否无故延迟或使用异常控制流程?,c#,asynchronous,exception-handling,async-await,task-parallel-library,C#,Asynchronous,Exception Handling,Async Await,Task Parallel Library,我不确定对代码中的事件做出反应的两种可能性。我最关心的是哪一个需要更少的资源。 我有一个方法,其中一个观测者注册到eventproducer。如果eventproducer返回某个内容,则该方法退出,并且该方法的调用方再次启动该方法(您可以将其视为一种长轮询) eventproducer有时每秒触发大量事件,有时会暂停几分钟 第一种方法是等待500毫秒的延迟,然后检查是否有返回的内容(直到超时5分钟)再次延迟500毫秒 eventProducer.RegisterListener((events
eventproducer
。如果eventproducer
返回某个内容,则该方法退出,并且该方法的调用方再次启动该方法(您可以将其视为一种长轮询)
eventproducer
有时每秒触发大量事件,有时会暂停几分钟
第一种方法是等待500毫秒的延迟,然后检查是否有返回的内容(直到超时5分钟)再次延迟500毫秒
eventProducer.RegisterListener((events)=>{evList.Add(events)});
while(evList.Count=0 && !TimeOut){
await Task.Delay(500);}
eventProducer.UnRegister(...);
// return evList, method gets recalled immediately
第二种方法是使用CancellationToken
。如果eventproducer
生成某些内容,则CancellationTokenSource
将取消该源。在方法中,我等待Task.Delay(5分钟,cancellationToken)
第二种方法的优点是,如果生产者产生了一些东西,该方法会立即返回,我们不必在循环中等待和唤醒
但是,对于第二种方法,每当生产者生成某些内容时,就会抛出一个TaskCanceledException
。我担心这会比每500毫秒唤醒和等待对系统负载的影响更大,尤其是当eventproducer
产生大量事件时
我是否高估了抛出和捕获异常的成本?有没有办法取消
任务。使用CancellationToken
延迟,但不抛出TaskCanceledException
?例如,类似于task.setComplete
?如果您希望获得与取消通知类似的即时通知,但没有例外,您只需使用TaskCompletionSource
TaskCompletionSource
是创建承诺任务的方式。您从任务
属性中获得一个未完成的任务,然后使用设置结果
完成它(或取消)。您可以使用它来实际传递结果本身:
var tcs = new TaskCompletionSource<Events>();
eventProducer.RegisterListener(events => tcs.SetResult(events));
var result = await tcs.Task;
eventProducer.UnRegister(...);
您可以使用\u cancellationToken.WaitHandle.WaitOne(超时以毫秒为单位)代码>取而代之。它会在提供的超时后返回,或者在触发取消令牌时立即返回,而不会引发异常。谢谢,TaskCompletionSource与我要查找的完全一样!当使用“wait Task.Delay(1000,cancellationToken).ContinueWith(Task=>{});”时,为什么它不再抛出Task cancelled异常?在我尝试捕获之前,框架是否仍然需要在内部处理捕获并处理异常,还是不首先抛出异常?@snell面对任务。延迟任务仍然被取消,如果等待它,它仍然会抛出异常。但你不是在等待。。您正在等待一个没有任何作用的继续。因为它不做任何事情,也没有CancellationToken,所以它不能抛出任何异常。@i3arnon因此,在很小的程度上,使用TaskCompletionSource可能会更有效?我第一次听说它是在这个QA中,所以我对它相当陌生。在我看来,从语义上来说,取消延迟比提前完成延迟更重要,但是,如果取消的成本比完成成本大得多,那么在这种特定情况下,语义差异可以忽略不计。我认为任务必须在内部处理异常也可能是错误的,但这就是我的理解,只是当我不等待时,我不需要捕捉它,对吗?@Snellface在这种情况下实际上没有异常。。但是对于任务以外的事情。延迟可能会出现。等待已取消的任务会引发异常,但创建已取消的任务不需要异常。假设Task.Delay
方法返回TaskCompletionSource,而不是调用tcs.SetResult
它使用tcs.SetCanceled
。通过这种方式,delayTask
被取消,等待它将抛出异常,而任务本身不会捕获任何异常。它只是“更长时间”的占位符,看起来不会等待调用,而是会阻止线程。
var tcs = new TaskCompletionSource<Events>();
eventProducer.RegisterListener(events => tcs.SetResult(events));
var result = await tcs.Task;
eventProducer.UnRegister(...);
var delayTask = Task.Delay(1000, cancellationToken);
var continuationTask = delayTask.ContinueWith(task => { });
await continuationTask;