Task.Delay 值得取消吗? [英] Is Task.Delay Worth Cancellation?

查看:38
本文介绍了Task.Delay 值得取消吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近使用我在许多地方看到的取消模式重新实现了一大堆异步 WCF 服务方法 - 您在启动任务上等待 Task.WhenAny 和一个任务.延迟.当然,现有任务不可取消,但有望在以后的版本中解决.

I've recently reimplemented a whole bunch of async WCF service methods using the cancellation pattern I've seen described in a number of places - where you await a Task.WhenAny on a started task and a Task.Delay. Of course, the existing tasks aren't cancellable, but that will hopefully be addressed in a later release.

就我而言,Task.Delay 的默认持续时间由服务设置控制.在绝大多数情况下,结果是期望的任务在必要的时间内完成.设置通常很慷慨.

In my case, the default duration of the Task.Delay is governed by a service setting. In an overwhelming majority of cases, the outcome is that the hoped-for task completes in the requisite amount of time. The setting is often made generous.

我见过的大多数(但不是全部)示例都懒得取消 Task.Delay.这么便宜不值得担心吗?我知道取消会引发异常.如果我取消延迟,我应该处理异常吗?

Most of (but not all) the examples I've seen do not bother to cancel the Task.Delay. Is it so cheap it's not worth worrying about? I know that cancellation raises an exception. If I cancel the delay, should I be handling the exception?

这是我创建的所有服务方法都通过调用的方法:

Here's the method I've made that all the service methods are calling through:

private async Task<T> GetOrTimeout<T>( Task<T> task, [CallerMemberName] string caller = "" )
{
  using ( var cts = new CancellationTokenSource( ) )
  {
    try
    {
      var timeout = GetDelay( cts.Token );
      var first = await Task.WhenAny( task, timeout );
      if ( first == timeout ) throw new TimeoutException( Properties.Resources.TimeoutOccurredInService.Fmt( caller ) );
      cts.Cancel( );  //--> haven't been doing this. Should I?
      return await task;
    }
    catch ( Exception ex )
    {
      throw LoggedFaultException( ex, caller );
    }
  }
}

...创建延迟的方法如下所示:

...and the method that creates the delay would look like this:

private Task GetDelay( CancellationToken token )
{
  return Task
    .Delay( Properties.Settings.Default.ServiceMethodTimeout, token )
    .ContinueWith( _ => { }, TaskContinuationOptions.ExecuteSynchronously );
}

如果我不取消延迟,我是否会比必要的时间更长地保留资源?特别是,我担心 WCF 启动以调用服务方法的实例.我担心他们会削减服务配置的并发参数.超时设置非常粗糙.不取消似乎很浪费,但这对我来说都是全新的东西.

If I don't cancel the delay, am I holding onto resources way longer than necessary? In particular, I'm worried about the instances that WCF spins up to invoke the service methods. I'm worried they'll cut into the concurrency parameters that the service was configured with. The timeout setting is pretty coarse. It seems wasteful to not cancel, but this is all pretty new stuff to me.

由于取消涉及异常,而且我已经接受过不使用异常来传达状态的训练,这感觉就像我把自己描绘成一些我不完全理解的可怕的反模式.也许 Task.Delay 对我来说不是正确的选择.感觉就像我让它变得比我应该的更复杂.对这种情况的任何了解将不胜感激.

Since cancellation involves exceptions, and since I've been trained to not use exceptions to communicate state, this feels like I've painted myself into some awful anti-pattern that I don't fully understand. Perhaps Task.Delay isn't the right choice for me. It feels like I've made it more complicated than I should. Any light shed on the situation would be most appreciated.

推荐答案

首先,整个问题在性能方面可能可以忽略不计,只有在实际环境中测试后才应考虑其他问题.

First of all, this whole issue is probably negligible performance-wise and should only be considered otherwise after testing in a real environment.

但是,如果我们深入研究,Task.Delay 会创建一个在特定时间间隔后完成的任务.它通过创建一个新的 System.Threading.Timer(它实现了 IDisposable)来实现,它使用 ThreadPool 线程在间隔后完成承诺任务.

However if we dive in, Task.Delay creates a task that is completed after a certain interval. It does so by creating a new System.Threading.Timer (which implements IDisposable) that completes the promise task after the interval using a ThreadPool thread.

如果您大量"使用 Task.Delay,您可能会在它们有用很久之后仍然有大量浪费的资源.如果您还使用捕获任何引用的委托向 Task.Delay 任务添加任何延续,它们也会无缘无故地徘徊.

If you use Task.Delay "a lot" you can have a considerable amount of wasted resources hanging around long after they're useful. If you also add any continuations to the Task.Delay task with a delegate that captures any references they too will hang around with no reason.

所以是的,取消任务比让它用完更安全,尽管可能不会太多.

So yes, it's safer to cancel the task instead of letting it run out, though probably not by much.

这篇关于Task.Delay 值得取消吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆