C#のベストプラクティス。awaitでパラメーターを渡しても大丈夫ですか?


8

パラメータを渡しても大丈夫awaitですか?これを行うことの長所と短所は何ですか?

var results = MapResults(await GetDataAsync());

2
あなたがしていることはすべて、パラメーターを渡す前にタスクを解決することです。var x = await GetDataAsyncとまったく同じです。var results = MapResults(x); 違いはありません。通常は、自分で実装するコーディングガイドライン
Heinrich

1
コードの可読性。それは文字通り同じですvar result = await GetDataAsync(); var map = MapResults(result)
Zer0

@ Zer0どれが読み取り可能で、varの結果があるのですか?または単一行?
ドリューアギレ

@Heinrichうん、私はあなたに同意します。私は、コードに単一行を実行するためのいくつかの悪い習慣を適用していることを心配しています。
Drew Aguirre

3
@DrewAguirre:これらの最後の2つは完全に異なりラターを実行してはなりません。それが明確だったといいのですが。前者は非同期待機を行います。後者は、非同期ワークフローで同期待機を行います。ここで、非同期ワークフローが、現在のスレッドで将来的に作業スケジュールするとします。同期待機は、「このスレッドが将来実行する作業が完了するまでこのスレッドをスリープする」ことを意味し、明らかに永久にスリープします。
Eric Lippert

回答:


28

更新:この質問は、2020年3月の私のブログの主題でした。この問題の詳細については、こちらをご覧ください。興味深い質問をありがとう!


ここでは、引数リストの唯一のメンバーとして関数呼び出しをすることを意図していたと仮定します。

他の人が指摘したように、間に違いはありません

x = M(await FAsync());

そして

var f = await FAsync();
x = M(f);

そしてそれは同じです

var ftask = FAsync();
x = M(await ftask)

ですから、どのように書いてもかまいません、そうですか?

少し考えてみてください。


この特定のシナリオでは、3つのワークフローはすべて同じです。しかし、シナリオを少しだけ変えると、ここに潜在的な違いがあります。検討してください:

x = M(await FAsync(), await GAsync());

これは同じです

var f = await FAsync();
var g = await GAsync();
x = M(f, g);

このワークフローについて何を知っていますか? GAsyncタスクは、FAsyncタスクが完了するまで開始されません!しかし、2つのタスクを同時に実行する機会があり、現在のスレッドをより効率的に使用できるようです。おそらく、ワークフローは次のように記述した方がよいでしょう。

var ftask = FAsync();
var gtask = GAsync();
x = M(await ftask, await gtask);

これで、FAsyncタスクとGAsyncタスクの両方が開始され、両方が終了するまでMを呼び出しません。

私のアドバイスは、あなたがあなたの待つ場所を慎重に考えることです。覚えておいてのawaitは継続の前提条件が満たされるまでワークフローは非同期に一時停止し、非同期ワークフロー内のポイントであることを意図しています実際に前提条件になるまでタスクの待機を遅らせることができる場合は、パフォーマンスを向上させることができる場合があります。


もちろん、あなたが待っているタスクの根本的なマルチスレッドのサポートを知っていることは良いことです。データベースからデータを生成し、同じSqlConnectionまたはDbContextを使用する2つのタスクを同時に待つことはできません。
Sebazzz

1
うわー!私は感心しました。ごめんなさい、あなたの答えに返信しませんでした。私はこれを答えとしてマークしました。そして私もあなたのブログを読みました。そして...それを維持
ドリュー・アギーレ

5

ランタイムに違いはありません。

var results = MapResults(await GetDataAsync())

そして

var tmp = await GetDataAsync();
var results = MapResults(tmp)

うん違いはありません。私が考えていること、これを行うための技術的な問題はありますか?または「tmp」変数を使用する方がきれいですか?最初の行を使用することに不利な点は見当たりません。例外があっても、GetDataAsync()にスローされます。
ドリューアギレ

最初の行を行うのは悪い習慣ですか?
ドリューアギレ

私は2番目のパターンを好みます。1)より読みやすく、2)結果に渡す前にコードをマッサージできます。
Harris Yer

OP GetDataAsyncはメソッド呼び出しではなく変数()を使用したことに注意してください。それTask GetDataAsync = CallSomeAsync()が初期化される場所に応じて、タスクMapResults(await GetDataAsync)が呼び出されるまでにタスクがすでに実行されているため、大きな違いがある可能性があります。詳細については、Ericの回答を参照してください。
Alexei Levenkov

ええ、十分なコンテキストがなかったので、それはタイプミスだと思いました...
ジェレミーレイクマン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.