【问题标题】:How to debug a await statement?如何调试等待语句?
【发布时间】:2013-03-20 00:04:11
【问题描述】:

我最近看到了一些关于 TPL 和异步模式的演示,所以我开始了一个小项目来尝试一些东西。 (异步和并行的东西)

我注意到 SqlConnection 有一个 OpenAsync() 方法,所以我想尝试等待这个。据我了解, await 关键字告诉编译器检查操作是否完成,如果未完成,它将把其余代码转换为继续任务。我也明白我应该仍然能够调试代码。但是,我遇到了一些问题。

我写了如下简单的测试代码:

Async Sub Gogo()
    Try
        Await connection1.OpenAsync()
    Catch ex As Exception
        Console.WriteLine(ex)
    End Try
    SomeCode()
End Sub

当我运行此代码(控制台应用程序)时会发生什么,我确实进入了 await 语句,但没有进一步。我尝试在 catch 语句和 try 块后面的代码中设置断点。两者都没有到达,控制台应用程序简单地退出。我不明白这里发生了什么。

我正在使用 VS2012 更新 1,(VB).Net 4.5。另外,因为我怀疑发生了一些错误(这似乎没有什么意义,因为当我使它同步时代码可以工作)我将 app.config 配置为升级未观察到的异常:

<runtime>
    <ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>      

但是,到目前为止,我没有遇到任何异常。 我错过了什么?请帮忙:)

【问题讨论】:

    标签: vb.net async-await


    【解决方案1】:

    两者都没有到达,控制台应用程序简单地退出。

    问题是您在控制台应用程序中使用它。如果您要在 Windows 窗体或 WPF 应用程序中执行相同的操作,您会看到非常不同的行为。

    当您调用Await 时,异步操作会尝试捕获调用者的同步上下文,然后继续处理该上下文。在控制台应用程序中,没有同步上下文(因为没有消息泵等),因此创建的延续被安排在 ThreadPool 线程上。

    异步操作开始,然后事情继续 - 控制台应用程序结束,因为它到达 Main() 例程的末尾,之后您永远不会“看到”这些东西。

    如果你想看到这些事情发生,你需要在你的控制台应用程序中添加一些东西来阻止它完成。例如,您可以使用ManualResetEvent 并将其设置在SomeCode() 之后,然后在您的Main() 例程中调用WaitOne()。这将使应用程序保持活动状态,直到您的异步操作完成。

    话虽如此,如果您想了解Async/Await,我建议您在GUI 应用程序而不是控制台应用程序中“玩”。当您安装了适当的同步上下文(在 Windows 窗体和 WPF 中自动发生)时,查看和理解正在发生的事情要简单得多。

    【讨论】:

    • 好的,谢谢。我没有意识到我的 Main 例程完成了,但显然是这样。不知道我怎么会错过:)
    • 我稍微改写了一下,并使用 Thread.Sleep 保持主线程处于活动状态并查看发生的情况。这似乎比您建议的 ManualResetEvent 东西容易一些?否则,您可能正确地使用 GUI 应用程序作为更合乎逻辑的上下文,但如前所述,我想同时尝试一些事情 :) 谢谢!
    猜你喜欢
    • 2019-12-09
    • 2020-07-23
    • 1970-01-01
    • 2019-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多