代码之家  ›  专栏  ›  技术社区  ›  Frank

为什么taskFactory.startNew方法不是泛型方法?

  •  8
  • Frank  · 技术社区  · 15 年前

    使用.NET 4.0中的TPL启动新的仅副作用任务(即:不返回结果的任务)的IDomatic方法使用以下API:

    Task Task.Factory.StartNew(Action<object>, object)   
    

    但是为什么这个API的签名不像这样

    Task Task.Factory.StartNew<T>(Action<T>, T) 
    

    或者像这样

    Task Task.Factory.StartNew<T>(T, Action<T>) 
    

    技术原因还是其他原因?

    2 回复  |  直到 14 年前
        1
  •  7
  •   Jon Skeet    15 年前

    好吧,现在我已经完全理解了这个问题。)

    我相信这是因为这是一个 direct replacement for ThreadPool.QueueUserWorkItem . 我同意这有点奇怪…但是 如果 无论如何,您使用的是lambda表达式,使用 取一个状态参数(即 Action 而不是 Action<object> )只需事先捕捉你感兴趣的价值。如果您分别指定值和函数,则没有帮助:(

        2
  •  3
  •   Jonathan B.    14 年前

    根据StephenToub(MSFT)的一篇文章,他们假设我们将依靠闭包来传递状态数据。还有一些关于签名模糊的借口。( http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/1988294c-de41-476a-a104-aa550b7409f5 )

    然而,依赖闭包来解决这个问题似乎是一个暂时的黑客等待更好的解决方案。它是有效的,但它不是一个好的长期解决方案。很多时候,简单地将委托方法指定为操作是最简单的方法,但这意味着我们必须使用全局变量,否则我们将被排除在状态参数传递之外。

    我喜欢雨果的一个建议(来自微软论坛的帖子)。雨果建议引入一个taskstate类型,这似乎是一个巧妙的方法来规避泛型的歧义问题。

    将此应用于task.factory.startNew()签名和task()构造函数,如下所示:

      public Task<T>( Action<T> function, TaskState<T> state );
      public Task<T,TResult>( Func<T,TResult> function, TaskState<T> state );
    

    actionstate非常类似于nullable类——只是一个值成员周围的简单包装器。实际上,使用taskstate可能如下所示:

      var myTask = new Task( MyMethod, new TaskState( stateInfo ) );
      ...
    
      public void MyMethod( StateInfo stateInfo ) { ... }
    

    taskstate解决方案并不完美,但似乎比依赖类型转换的闭包更好。