为什么 TaskFactory.StartNew 方法不是通用的?

发布于 2024-08-13 04:12:21 字数 377 浏览 7 评论 0原文

在 .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>) 

技术原因或其他原因?

The idomatic way to start a new side-effect-only task (that is: a task that returns no result) using the TPL in .NET 4.0 is using the following API:

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

But why doesn't the signature of this API look like this

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

or like this

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

Technical reasons or some other reason?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

习惯成性 2024-08-20 04:12:21

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

我相信这是因为这意味着 直接替换ThreadPool.QueueUserWorkItem。我确实同意这看起来有些奇怪......但是如果你无论如何都在使用lambda表达式,那么使用确实采用状态参数的版本可能会更容易(即Action 而不是 Action),并预先捕获您感兴趣的值。如果您单独指定值和函数,这没有帮助:(

Okay, now that I understand the question properly :)

I believe it's because this is meant to be a direct replacement for ThreadPool.QueueUserWorkItem. I do agree that it seems somewhat odd... but if you're using lambda expressions anyway, it's probably easier to use the version that does take a state parameter (i.e. Action instead of Action<object>) and just capture the value you're interested in beforehand. It doesn't help if you're specifying the value and the function separately :(

十六岁半 2024-08-20 04:12:21

根据 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 ) { ... }

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

According to a post by Stephen Toub (MSFT), they are assuming that we are going to rely on closures to pass state data. There was also some excuse about signature ambiguity. (http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/1988294c-de41-476a-a104-aa550b7409f5)

However, relying on closures to solve this problem seems like a temporary hack waiting for a better solution. It works, but it's not a good longer-term solution. There are many times that simply specifying a delegate method as the action would be the simplest approach, but that means we have to use global vars or we're excluded from state parameter passing.

I like one of Hugo's proposals (from the MS forum posting). Hugo suggested introducing a TaskState type, which seems like a clever way to circumvent the generics ambiguity issue.

Applying this to the Task.Factory.StartNew() signature and the Task() constructor as such:

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

ActionState would be a lot like the Nullable class -- just a simple wrapper around a Value member. In practice, using TaskState might look like this:

  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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文