Task.Delay是否值得取消?

时间:2015-09-06 18:37:46

标签: c# .net wcf async-await task-parallel-library

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

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

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

以下是我所提出的所有服务方法都在调用的方法:

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 );
    }
  }
}

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

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

如果我没有取消延迟,我是否会持续超过必要的资源?特别是,我担心WCF旋转调用服务方法的实例。我担心他们会切入配置服务的并发参数。超时设置非常粗糙。没有取消似乎很浪费,但这对我来说都是很新的东西。

由于取消涉及例外情况,并且由于我已接受过不使用例外来表达状态的培训,因此我感觉自己已经将自己描绘成一些我不完全理解的可怕的反模式。也许Task.Delay对我来说不是正确的选择。 感觉就像我使它变得比我应该更复杂。任何有关这种情况的灯光都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

首先,整个问题在性能方面可能是微不足道的,只有在真实环境中进行测试后才应该考虑其他问题。

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

如果您使用Task.Delay&#34;很多&#34;在它们有用之后很久就会有相当多的浪费资源。如果你还向post_class()任务添加任何延续,并且代理人捕获任何引用,他们也会毫无理由地挂起。

所以是的,取消任务而不是让它耗尽更安全,但可能不是很多。

答案 1 :(得分:1)

当您关心应用程序的关闭速度时,Task.Delay 值得取消。

一个例子是 asp.net 网络应用程序。

当服务器回收您的网络应用程序时(例如,当它正在实时更新时)它需要一切快速结束。如果您有在后台等待的任务,尤其是通过 QueueBackgroundObject 或类似技术注册的任务,应用可能需要一段时间才能关闭。