为什么 TaskFactory.StartNew 方法不是通用的?
在 .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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,现在我正确理解了这个问题:)
我相信这是因为这意味着 直接替换
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 ofAction<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 :(根据 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() 构造函数,如下所示:
ActionState 非常类似于 Nullable 类 —— 只是 Value 成员的简单包装。实际上,使用 TaskState 可能如下所示
:解决方案并不完美,但它似乎是比依赖类型转换闭包更好的解决方案。
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:
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:
The TaskState<> solution is not perfect, but it seems like a much better solution than relying on closure of type casting.