1. ホーム
  2. c#

[解決済み] voidを返すことと、Taskを返すことの違いは何ですか?

2022-06-08 08:10:59

質問

様々な C# 非同期 CTP サンプルを見ていると、いくつかの非同期関数が void を返す非同期関数もあれば、一般的でない Task . を返す理由はわかります。 Task<MyType> を返すことは、非同期処理が完了したときに呼び出し元にデータを返すのに便利であることはわかりますが、私が見た関数の中で、戻り値の型が Task を返す関数は、決してデータを返しません。 なぜ void ?

どのように解決するのですか?

SLaksとKillercamの回答は良いものです。私はもう少し文脈を追加しようと思いました。

最初の質問は、基本的にどのメソッドにマークが付けられるかについてです async .

としてマークされたメソッドは async を返すことができます。 void , Task または Task<T> . これらの違いは何ですか?

A Task<T> を返す非同期メソッドは待ち受けることができ、タスクが完了するとTをプロファリングします。

A Task を返す非同期メソッドを待ち受けにすることができ、タスクが完了するとその続きが実行されるようにスケジューリングされます。

A void を返す非同期メソッドは待ち受けることができません; それは "fire and forget" なメソッドです。それは非同期で動作し、それがいつ完了したかを知る方法はありません。SLaksが言うように、普通は非同期のイベントハンドラを作るときだけそうする。イベントが発生し、ハンドラが実行されます。イベントハンドラが返すタスクは、イベントハンドラはタスクを返さないので、誰もquot;await"しようとしませんし、たとえそうだとしても、どんなコードがタスクを使って何かに使うでしょうか?イベントハンドラはタスクを返さないので、イベントハンドラによって返されたタスクをquait"する人はいません。

コメントでの 2 つ目の質問は、本質的に、何が await を編集することです。

どのようなメソッドが await にはどのようなメソッドがあるのでしょうか?void リターンのメソッドは await になるのでしょうか?

いいえ、void リターンのメソッドは待ち受けできません。コンパイラは await M() への呼び出しに変換します。 M().GetAwaiter() を呼び出すことになります。 GetAwaiter はインスタンスメソッドか拡張メソッドである可能性があります。待ち受ける値は、待ち受けを得ることができるものでなければなりません。明らかに、 void-returnメソッドは待ち受けを得ることができる値を生成しないのです。

Task void-returnメソッドはawaitable値を生成することができます。私たちは、サードパーティが独自の Task -のようなオブジェクトを実装し、それを待ち受けることができるようになるでしょう。しかし async 以外のものを返すメソッドを宣言することはできません。 void , Task または Task<T> .

(UPDATE: 私の最後の文は、C#の将来のバージョンによって改竄されるかもしれません。非同期メソッドにタスク型以外の戻り値の型を許可する提案があります)。

(UPDATE:上記の機能はC# 7に取り込まれました)。