[英]Should this code return a Task or Task<object>?
I was reading The Nature of TaskCompletionSource , a post by Stephen Toub. 我正在阅读The Task of TaskCompletionSource ,这是Stephen Toub的一篇文章。
public static Task RunAsync(Action action)
{
var tcs = new TaskCompletionSource<Object>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
action();
tcs.SetResult(null);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Since we no longer care what the type of
T
is, I've defaulted to usingObject
. 由于我们不再关心T
的类型,我默认使用Object
。 Then, when theAction
is executed successfully,SetResult
is still used to transition theTask
into theRanToCompletion
final state; 然后,当Action
成功执行时,SetResult
仍然用于将Task
转换为RanToCompletion
最终状态; however, since the actual result value is irrelevant,null
is used. 但是,由于实际结果值无关紧要,因此使用null
。 Finally,RunAsync
returnsTask
rather thanTask<Object>
. 最后,RunAsync
返回Task
而不是Task<Object>
。 Of course, the instantiatedtask
's type is stillTask<Object>
, but we need not refer to it as such, and the consumer of this method need not care about those implementation details. 当然,实例化的task
的类型仍然是Task<Object>
,但是我们不需要这样引用它,并且该方法的使用者不需要关心那些实现细节。
I don't particularly understand why the method should return Task
rather than Task<object>
(which is why I emphasised the bold sentence). 我不是特别理解为什么该方法应该返回Task
而不是Task<object>
(这就是我强调粗体句子的原因)。 I know the method is set to return Task
but tcs
is a TaskCompletionSource<Object>
, not TaskCompletionSource
(which is wrong, I think). 我知道该方法设置为返回Task
但是tcs
是TaskCompletionSource<Object>
,而不是TaskCompletionSource
(我认为这是错误的)。
There isn't a non generic TaskCompletionSource
and considering all you want is a task without a result, the result doesn't matter. 没有非通用的TaskCompletionSource
并且考虑到你想要的只是一个没有结果的任务,结果无关紧要。 The caller doesn't know and doesn't care in this case that the Task is actually a Task<object>
, The caller just await
s it, and gets an exception if there is one. 在这种情况下,调用者不知道也不关心Task实际上是一个Task<object>
,调用者只是await
它,并且如果有的话就会获得异常。 The caller is unaware of the actual result. 呼叫者不知道实际结果。
This of course is facilitated by the fact that Task<T>
inherits from Task
这当然是由Task<T>
继承自Task
的事实所促成的
It's also common to find a Task<bool>
that returns false, or Task<int>
with 0. 找到返回false的Task<bool>
或使用0返回Task<int>
也很常见。
There is no non-generic TaskCompletionSource
class for creating instances of Task
which are not instances of Task<T>
. 没有用于创建Task
实例的非通用TaskCompletionSource
类,它们不是Task<T>
实例。 This leaves two options for the generic type parameter for TaskCompletionSource<T>
when you don't care about (or are not providing) the return value: 当您不关心(或不提供)返回值时,这为TaskCompletionSource<T>
的泛型类型参数留下了两个选项:
object
, as the return type. 使用任意现有类型(如object
)作为返回类型。 Set the value to null
to indicate completion of the task. 将值设置为null
以指示任务完成。 null
to indicate completion of the task. 使用特定的非公共类型,并将值设置为null
以指示任务的完成。 When I create a TaskCompletionSource<T>
instance for the purpose of providing a Task
with no return value, I prefer to use a dedicated non-public type to ensure consuming code will not mistake the returned Task
as an instance of Task<T>
where the result has meaning. 当我创建一个TaskCompletionSource<T>
实例以提供没有返回值的Task
时,我更喜欢使用专用的非公共类型来确保使用代码不会将返回的Task
误认为Task<T>
的实例结果有意义。
First, I define the following class (it can be a private sealed class
if it's nested within another type): 首先,我定义了以下类(如果嵌套在另一个类型中,它可以是private sealed class
):
internal sealed class VoidResult
{
}
Then, instead of using TaskCompletionSource<object>
for the completion source, I use TaskCompletionSource<VoidResult>
. 然后,我使用TaskCompletionSource<VoidResult>
而不是使用TaskCompletionSource<object>
作为完成源。 Since the VoidResult
type is not accessible by calling code, the user will be unable to cast the Task
object to an instance of Task<VoidResult>
. 由于无法通过调用代码访问VoidResult
类型,因此用户将无法将Task
对象Task<VoidResult>
为Task<VoidResult>
的实例。
I don't particularly understand why the method should return
Task
rather thanTask<object>
我不特别理解为什么该方法应该返回Task
而不是Task<object>
Because when you return Task<Object>
it means that when this method completes it will produce some useful value of type Object
. 因为当您返回Task<Object>
这意味着当此方法完成时,它将生成一些Object
类型的有用值。 in this case we're not producing any result, That's why stephen choose to return Task
. 在这种情况下,我们没有产生任何结果,这就是为什么stephen选择返回Task
。
If we're dealing with Func<Object>
then returning Task<Object>
would be appropriate, as Func
will produce some result, we may choose to return it. 如果我们处理Func<Object>
然后返回Task<Object>
是合适的,因为Func
会产生一些结果,我们可能会选择返回它。
Why
TaskCompletionSource<Object>
, notTaskCompletionSource
? 为什么TaskCompletionSource<Object>
,而不是TaskCompletionSource
?
Because there's no such thing. 因为没有这样的事情。 There is no non generic TaskCompletionSource
. 没有非通用的TaskCompletionSource
。
If you returned a Task<object>
, then var result = await RunAsync(...)
would always return null
, since that's what you're setting the result to. 如果您返回了Task<object>
,则var result = await RunAsync(...)
将始终返回null
,因为这是您要将结果设置为。
The client doesn't care about this, so you just return a Task
. 客户端不关心这个,所以你只需要返回一个Task
。
Ideally, you would use a TaskCompletionSource
internally, instead of a TaskCompletionSource<object>
, and just call something like SetCompleted()
instead of SetResult(null)
. 理想情况下,您可以在内部使用TaskCompletionSource
,而不是使用TaskCompletionSource<object>
,只需调用SetCompleted()
而不是SetResult(null)
。 But such type does not exist. 但这种类型不存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.