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).Net4.5を使用しています。また、何らかのエラーが発生したと思われるため(同期させるとコードが機能するため、実際には意味がないようです)、監視されない例外をエスカレートするようにapp.configを構成しました。

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

しかし、今のところ例外はありません。私は何が欠けていますか?助けてください :)

4

1 に答える 1

6

どちらにも到達せず、コンソール アプリケーションは単純に終了します。

問題は、これをコンソール アプリケーションで使用していることです。Windows フォームまたは WPF アプリで同じことを行うと、まったく異なる動作が見られます。

を呼び出すAwaitと、非同期操作は呼び出し元の同期コンテキストをキャプチャしようとし、そのコンテキストで続行します。コンソール アプリケーションでは、(メッセージ ポンプなどがないため) 同期コンテキストがないため、作成された継続は ThreadPool スレッドでスケジュールされます。

非同期操作が開始され、その後、処理が続行されます。コンソール アプリケーションは終了します。これは、Main() ルーチンの最後に到達したためであり、その後は何も表示されません。

何かが起こるのを見たい場合は、コンソール アプリケーションが完了しないように何かを追加する必要があります。たとえば、 a を使用して のManualResetEvent後に設定し、 Main() ルーチンSomeCode()で呼び出すことができます。WaitOne()これにより、非同期操作が完了するまでアプリケーションが存続します。

Asyncそうは言っても、 /を理解しようとしている場合Awaitは、コンソール アプリケーションではなく GUI アプリケーションで「プレイ」することをお勧めします。Windows フォームと WPF で自動的に行われる適切な同期コンテキストがインストールされていると、何が起こっているのかを見て理解するのがはるかに簡単になります。

于 2013-03-19T16:04:11.577 に答える