【问题标题】:Return type of Task.Run vs. Task.Factory.StartNewTask.Run 与 Task.Factory.StartNew 的返回类型
【发布时间】:2015-01-22 02:15:32
【问题描述】:

我一直在反复阅读 Stephen Cleary 的文章 StartNew is Dangerous 和 Stephen Toub 的文章 Task.Run vs Task.Factory.StartNew。我正在尝试理解这一点。

给定以下代码:

Dim s = Await Task.Factory.StartNew(New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function))

Dim t = Await Task.Run(New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function))

为什么sTask(Of String) 类型,而tString 类型(这是我所期望的)?

我还可以执行以下操作:

Dim u = Await New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function).Invoke()

其中uString,我可以添加函数:

Async Function GetValueAsync() As Task(Of String)
    Await Task.Delay(10000)
    Return "Hello"
End Function

然后像这样使用它:

Dim v = Await GetValueAsync()

v 也是String

那么为什么s 不是字符串呢?

在 Stephen Cleary 的文章(如上链接)中,他说:

[Task.Factory.StartNew] 不理解异步委托...问题 是当您将异步委托传递给 StartNew 时,很自然 假设返回的任务代表该委托。然而,由于 StartNew 不了解异步委托,该任务实际上是什么 代表只是该委托的开始。

我觉得这是整个事情的关键,但我不明白“那个任务实际上代表的只是那个委托的开始。” “那个委托的开始”是什么意思?

【问题讨论】:

    标签: vb.net delegates async-await


    【解决方案1】:

    您可以将Await 视为将Task(Of T)“解包”为结果类型T

    为什么 s 是 Task(Of String) 类型而 t 是 String 类型(这是我所期望的)?

    Task.Factory.StartNew(New Func(Of Task(Of String))(...) 的类型是Task(Of Task(Of String)),因此Await 将其展开为Task(Of String)

    Task.Run(New Func(Of Task(Of String))(...) 的类型是Task(Of String),因此Await 将其展开为String

    “那个委托的开始”是什么意思?

    正如我在Async Intro 中所描述的,每个异步方法都开始同步执行,并且仅在第一个Await 处变为异步。所以,如果你使用Task.Factory.StartNew,它会返回一个Task(Of Task(Of T))。 “外部”任务表示委托的同步执行,直到Await 第一次决定向其调用者让步。此时,Await返回 Task(Of T) 给它的调用者。这个返回的任务是Task(Of Task(Of T)) 的“内部”任务,它代表异步委托的完成

    但您真正需要知道的唯一一件事是只使用Task.Run 而不是Task.Factory.StartNew

    【讨论】:

    • 好的,所以当 S. Taub 在他的文章中说“当您将 Action 传递给 Task.Run 时:Task.Run(someAction);这完全等效到:@987654345 @”(强调添加)正如他所说,它只是“等效”,因为该操作不返回任何内容,所以我们从该调用中真正得到的是一个 Task(Of String),然后它被“解包”成一个 String,因为Await?
    • @roryap:您的原始代码都没有使用Action。如果您传递了 Action 委托,则该声明是正确的。如果您通过Func<Task>Func<Task<T>>,则它不成立。 Stephen 稍后在声明“Task.Run 的 this 重载的实现基本上等同于 ...”时澄清了这一点
    • 非常感谢,这对我帮助很大。
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2015-06-23
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2020-09-20
    • 2023-03-22
    相关资源
    最近更新 更多