308

このような方法を書くシナリオはありますか:

public async Task<SomeResult> DoSomethingAsync()
{
    // Some synchronous code might or might not be here... //
    return await DoAnotherThingAsync();
}

これの代わりに:

public Task<SomeResult> DoSomethingAsync()
{
    // Some synchronous code might or might not be here... //
    return DoAnotherThingAsync();
}

理にかなっていますか?

内部呼び出しからreturn await直接戻ることができるのに、なぜコンストラクトを使用するのでしょうか?Task<T>DoAnotherThingAsync()

非常に多くの場所で のコードを目にしますreturn awaitが、何か見落としているのではないかと思います。しかし、私が理解している限りでは、この場合 async/await キーワードを使用せず、 Task を直接返すことは機能的に同等です。await追加レイヤーのオーバーヘッドを追加するのはなぜですか?

4

7 に答える 7

119

必要がない場合async(つまり、 を直接返すことができる場合Task) は、使用しないでくださいasync

実行する非同期操作が2 つreturn awaitある場合など、 が役立つ状況がいくつかあります。

var intermediate = await FirstAsync();
return await SecondAwait(intermediate);

パフォーマンスの詳細については、このトピックに関するasyncStephen Toub のMSDN 記事ビデオを参照してください。

更新:より詳細なブログ記事を書きました。

于 2013-09-30T15:35:06.607 に答える
25

The only reason you'd want to do it is if there is some other await in the earlier code, or if you're in some way manipulating the result before returning it. Another way in which that might be happening is through a try/catch that changes how exceptions are handled. If you aren't doing any of that then you're right, there's no reason to add the overhead of making the method async.

于 2013-09-30T15:35:37.327 に答える
19

結果を待つ必要がある別のケースは次のとおりです。

async Task<IFoo> GetIFooAsync()
{
    return await GetFooAsync();
}

async Task<Foo> GetFooAsync()
{
    var foo = await CreateFooAsync();
    await foo.InitializeAsync();
    return foo;
}

この場合、の型が2 つのメソッド間で異なり、 に直接代入できないため、GetIFooAsync()は の結果を待つ必要があります。しかし、結果を待っていると、 に直接代入できるようになるだけです。次に、非同期メソッドは、結果を内部と外部に再パッケージ化します。GetFooAsyncTTask<Foo>Task<IFoo>FooIFooTask<IFoo>

于 2015-05-08T15:30:26.960 に答える
11

return await を使用しない場合、デバッグ中または例外のログに出力されたときにスタック トレースが台無しになる可能性があります。

タスクを返すと、メソッドはその目的を果たし、コール スタックから外れています。使用return awaitすると、コールスタックに残されます。

例えば:

await 使用時のコール スタック: A が B からのタスクを待機中 => B が C からのタスクを待機中

await を使用しない場合のコール スタック: B が返した C からのタスクを待機している A。

于 2019-01-16T06:16:45.043 に答える
9

それ以外の場合は単純な「サンク」メソッドを非同期にすると、メモリ内に非同期ステート マシンが作成されますが、非同期ステート マシンは作成されません。非非同期バージョンの方が効率的であるため (これは事実です)、多くの人が非非同期バージョンを使用することを指摘する可能性がありますが、ハングが発生した場合、そのメソッドが「リターン/継続スタック」に関与しているという証拠がないことも意味します。これにより、ハングを理解することがより困難になることがあります。

そうです、パフォーマンスが重要でない場合 (通常はそうではありません)、これらすべてのサンク メソッドに非同期をスローして、後でハングを診断するのに役立つ非同期ステート マシンを用意します。 thunk メソッドは時間の経過とともに進化し、throw ではなく、失敗したタスクを確実に返すようになります。

于 2015-05-08T15:34:37.107 に答える