さまざまなC#非同期CTPサンプルを見るvoidと、を返す非同期関数と、非ジェネリックを返す関数がありTaskます。Task<MyType>非同期操作が完了したときに呼び出し元にデータを返すのにa を返すと便利な理由がわかりますが、これまでに見た関数の戻り値の型にTaskは、データを返さないものがあります。なぜ戻りませんvoidか?
さまざまなC#非同期CTPサンプルを見るvoidと、を返す非同期関数と、非ジェネリックを返す関数がありTaskます。Task<MyType>非同期操作が完了したときに呼び出し元にデータを返すのにa を返すと便利な理由がわかりますが、これまでに見た関数の戻り値の型にTaskは、データを返さないものがあります。なぜ戻りませんvoidか?
回答:
SLaksとKillercamの答えは良いです。もう少しコンテキストを追加すると思いました。
最初の質問は基本的に、どのメソッドをマークできるかについてasyncです。
async戻り可能としてマークされたメソッドvoid、TaskまたはTask<T>。それらの違いは何ですか?
Task<T>返す非同期メソッドを待つことができ、タスクが完了すると、それはT.を差し出すます
Task返す非同期メソッドを待つことができ、タスクの完了は、タスクの継続を実行するようにスケジュールされている場合。
void返す非同期メソッドを待つことはできません。「ファイアアンドフォーゲット」方式です。非同期で動作し、いつ完了したかを知る方法はありません。これは少し奇妙なことです。SLaksが言うように、通常は非同期イベントハンドラーを作成するときにのみそれを行います。イベントが発生すると、ハンドラーが実行されます。イベントハンドラーはタスクを返さないため、誰もイベントハンドラーによって返されるタスクを「待つ」ことはできません。通常、そもそもハンドラーに制御を移すのはユーザーコードではありません。
コメントの2番目の質問は、本質的には何をawait編集できるかについてです。
どのような方法で
await編集できますか?ボイドを返す方法はawait編集できますか?
いいえ、ボイドを返すメソッドを待つことはできません。コンパイラは、翻訳await M()への呼び出しにM().GetAwaiter()、GetAwaiterインスタンスメソッドまたは拡張メソッドであるかもしれません。待機する値は、待機者を取得できる値でなければなりません。明らかにvoidを返すメソッドは、待機者を取得できる値を生成しません。
Task-returningメソッドは、待機可能な値を生成できます。私たちは、サードパーティがTask待つことができるようなオブジェクトの独自の実装を作成することを望み、あなたはそれらを待つことができるでしょう。ただし、宣言することはできませんasyncリターンは何もなく、その方法void、TaskまたはをTask<T>。
(更新:私の最後の文では、C#の将来のバージョンによって改ざんされる可能性があります。非同期メソッドのタスクタイプ以外の戻り値のタイプを許可する提案があります。)
(更新:上記の機能により、C#7に組み込まれました。)
async voidメソッドSynchronizationContextは、実行を開始したときにアクティブだったで例外を発生させます。これは、(同期)イベントハンドラーの動作に似ています。@DrewMarsh:UnobservedTaskExceptionおよびランタイム設定は、「ファイアアンドフォーゲット」非同期タスクメソッドにのみ適用され、メソッドには適用されませんasync void。
呼び出し元がタスクで待機するか、継続を追加する場合。
実際、戻る唯一の理由voidは、イベントハンドラを記述しているために戻ることができない場合ですTask。
voidそれが生成するタスクに到達する方法はありません。(実際には、それがa Taskを生成するかどうかさえ
メソッドは戻りTask、Task<T>合成可能です。つまりawait、asyncメソッド内でそれらを実行できます。
async返さvoidれるメソッドは合成可能ではありませんが、他に2つの重要なプロパティがあります。
2番目のポイントは、未処理の非同期操作の数を維持するコンテキストを扱うときに重要です。
ASP.NETコンテキストはそのようなコンテキストの1つです。非同期Taskメソッドからの待機をせずに非同期メソッドを使用するとvoid、ASP.NET要求が早く完了します。
もう1つのコンテキストは、AsyncContext単体テスト用に私が書いたものです(ここから入手できます)。このAsyncContext.Runメソッドは、未処理の操作の数を追跡し、ゼロになると戻ります。
タイプTask<T>は、タスクパラレルライブラリ(TPL)の主力タイプTであり、「将来的にタイプの結果を生成するいくつかの作業/ジョブ」の概念を表します。「将来は完了するが結果を返さない作業」の概念は、非ジェネリックタスクタイプで表されます。
タイプの結果がどのようTに生成されるか、および特定のタスクの実装の詳細は正確です。作業はローカルマシンの別のプロセスや別のスレッドなどにファームアウトされる可能性があります。TPLタスクは通常、現在のプロセスのスレッドプールからワーカースレッドにファームアウトされますが、その実装の詳細はTask<T>タイプの基本ではありません。むしろ、は、Task<T>を生成する高遅延オペレーションを表すことができTます。
上記のコメントに基づいて:
このawait式は、「この式を評価して、将来結果を生成する作業を表すオブジェクトを取得することを意味します。現在のメソッドの残りの部分を、そのタスクの継続に関連するコールバックとして登録します。そのタスクが生成されてコールバックされると、サインアップされている場合は、すぐに制御を呼び出し元に戻します。」これは、通常のメソッド呼び出しとは対照的/対照的です。つまり、「何をしているかを覚えて、完全に完了するまでこのメソッドを実行し、中断したところから再開して、メソッドの結果を把握する」ということです。
編集:2011年10月のMSDN MagazineのEric Lippertの記事を引用する必要があります。これは、最初にこのことを理解するのに非常に役立ちました。
その他の情報とホワイトページの読み込みについては、こちらをご覧ください。
これがお役に立てば幸いです。