9

在 .NET 4.0 中使用 TPL 启动新的仅副作用任务(即:不返回结果的任务)的惯用方式是使用以下 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>) 

技术原因还是其他原因?

4

2 回答 2

7

好的,现在我正确理解了这个问题:)

我相信这是因为这是为了直接替代ThreadPool.QueueUserWorkItem. 我确实同意这似乎有点奇怪......但如果你仍然使用 lambda 表达式,那么使用带有状态参数的版本(即而不是 )可能更容易,并且只是Action预先Action<object>捕获你感兴趣的值. 如果您分别指定值和函数,这将无济于事:(

于 2009-12-03T14:13:21.060 回答
3

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

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

我喜欢 Hugo 的一项建议(来自 MS 论坛发帖)。Hugo 建议引入 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 类——只是一个简单的 Value 成员包装器。在实践中,使用 TaskState 可能如下所示:

  var myTask = new Task( MyMethod, new TaskState( stateInfo ) );
  ...

  public void MyMethod( StateInfo stateInfo ) { ... }

The TaskState<> solution is not perfect, but it seems like a much better solution than relying on closure of type casting.

于 2011-03-11T21:44:47.930 回答