我正在读书 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;
}

因为我们不再关心什么类型 T 是的,我默认使用 Object. 。然后,当 Action 执行成功, SetResult 仍然用于过渡 Task 进入 RanToCompletion 最终状态;然而,由于实际结果值无关紧要, null 用来。 最后, RunAsync 回报 Task 而不是 Task<Object>. 。当然,实例化的 task的类型仍然是 Task<Object>, ,但我们不需要这样引用它,并且该方法的使用者不需要关心那些实现细节。

我不是特别明白为什么该方法应该返回 Task 而不是 Task<object> (这就是为什么我强调粗体句子)。我知道该方法设置为返回 Tasktcs 是一个 TaskCompletionSource<Object>, , 不是 TaskCompletionSource (我认为这是错误的)。

有帮助吗?

解决方案

没有非通用的 TaskCompletionSource 考虑到你想要的只是一项没有结果的任务,结果并不重要。在这种情况下,调用者不知道也不关心任务实际上是一个 Task<object>, 调用者只需 await是的,如果有的话就会得到一个例外。调用者不知道实际结果。

这当然是由以下事实促进的: Task<T> 继承自 Task


找到一个也很常见 Task<bool> 返回 false,或者 Task<int> 与 0。

其他提示

没有非通用的 TaskCompletionSource 用于创建实例的类 Task 哪些不是实例 Task<T>. 。这为泛型类型参数留下了两个选项 TaskCompletionSource<T> 当您不关心(或不提供)返回值时:

  1. 使用任意现有类型,例如 object, ,作为返回类型。将值设置为 null 来表示任务完成。
  2. 使用特定的非公共类型,并将值设置为 null 来表示任务完成。

当我创建一个 TaskCompletionSource<T> 实例的目的是提供 Task 由于没有返回值,我更喜欢使用专用的非公共类型来确保使用代码不会错误地返回 Task 作为一个例子 Task<T> 结果有意义。

首先,我定义以下类(它可以是 private sealed class 如果它嵌套在另一种类型中):

internal sealed class VoidResult
{
}

然后,不要使用 TaskCompletionSource<object> 对于完成源,我使用 TaskCompletionSource<VoidResult>. 。自从 VoidResult 类型无法通过调用代码访问,用户将无法强制转换 Task 对象的实例 Task<VoidResult>.

我不是特别明白为什么该方法应该返回 Task 而不是 Task<object>

因为当你回来时 Task<Object> 这意味着当这个方法完成时,它将产生一些有用的类型值 Object. 。在这种情况下,我们不会产生任何结果,这就是斯蒂芬选择返回的原因 Task.

如果我们正在处理 Func<Object> 然后返回 Task<Object> 是适当的,因为 Func 会产生一些结果,我们可以选择返回它。

为什么 TaskCompletionSource<Object>, , 不是 TaskCompletionSource?

因为没有这样的事情。没有非通用的 TaskCompletionSource.

如果您退回了 Task<object>, , 然后 var result = await RunAsync(...) 总会回来 null, ,因为这就是您要设置的结果。

客户并不关心这个,所以你只需返回一个 Task.

理想情况下,您会使用 TaskCompletionSource 内部,而不是 TaskCompletionSource<object>, ,然后调用类似的东西 SetCompleted() 代替 SetResult(null). 。但这种类型并不存在。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top