4

我最近看了一些关于 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>      

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

4

1 回答 1

6

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

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

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

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

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

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

于 2013-03-19T16:04:11.577 回答