如何调试await语句?

时间:2013-03-19 16:00:00

标签: vb.net async-await

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

我注意到SqlConnection有一个OpenAsync()方法,所以我想尝试等待这个。据我所知,await关键字告诉compliler检查操作是否完成,如果不是,它会将其余代码转换为continuation任务。我也明白我仍然可以调试代码。但是,我遇到了一些问题。

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

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>      

但是,到目前为止我没有得到任何例外。 我错过了什么?请帮助:)

1 个答案:

答案 0 :(得分:6)

  

两者都未到达,控制台应用程序只是退出。

问题是您在控制台应用程序中使用它。如果你在Windows窗体或WPF应用程序中做同样的事情,你会看到非常不同的行为。

当您调用Await时,异步操作会尝试捕获调用方的同步上下文,然后继续该上下文。在控制台应用程序中,没有同步上下文(因为没有消息泵等),因此创建的continuation将在ThreadPool线程上进行调度。

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

如果您希望看到这些内容发生,您需要在控制台应用程序中添加一些内容以防止它完成。例如,您可以使用ManualResetEvent并在SomeCode()之后设置它,并在Main()例程中调用WaitOne()。这将使应用程序保持活动状态,直到异步操作完成。

话虽如此,如果您正在尝试理解Async / Await,我建议您在GUI应用程序中“播放”而不是控制台应用程序。当您安装了适当的同步上下文时,可以更加简单地查看和了​​解发生的情况,这在Windows窗体和WPF中会自动发生。