[解決済み】linq selectで非同期await。
質問
既存のプログラムを修正する必要があり、以下のコードが含まれています。
var inputs = events.Select(async ev => await ProcessEventAsync(ev))
.Select(t => t.Result)
.Where(i => i != null)
.ToList();
しかし、これは私には非常に奇妙に思えます。
async
と
await
をセレクトしてください。によると
この答え
by Stephen Cleary それらを削除することができるはずです。
次に、2番目の
Select
で、その結果を選択します。これはタスクが全く非同期ではなく、同期的に実行されることを意味しませんか(無駄に労力がかかる)、それともタスクは非同期的に実行され、それが完了したら残りのクエリが実行されるのでしょうか?
に従って、上記のコードを次のように書けばよいのでしょうか? Stephen Clearyによる別の回答 :
var tasks = await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev)));
var inputs = tasks.Where(result => result != null).ToList();
と、このように完全に同じなのでしょうか?
var inputs = (await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev))))
.Where(result => result != null).ToList();
このプロジェクトに取り組んでいる間、最初のコードサンプルを変更したいのですが、(明らかに動作している)非同期コードを変更するのはあまり気が進みません。もしかしたら、私は無駄に心配しているだけで、3つのコードサンプルはすべて全く同じことを行っているのでしょうか?
ProcessEventsAsyncはこのような感じです。
async Task<InputResult> ProcessEventAsync(InputEvent ev) {...}
解決方法は?
var inputs = events.Select(async ev => await ProcessEventAsync(ev))
.Select(t => t.Result)
.Where(i => i != null)
.ToList();
まず、asyncとawaitがselectで使われていることです。Stephen Clearyの回答によると、これらを削除することができるはずです。
の呼び出しは
Select
が有効です。この2行は基本的に同じです。
events.Select(async ev => await ProcessEventAsync(ev))
events.Select(ev => ProcessEventAsync(ev))
(からの同期例外の投げ方については、若干の違いがあります。
ProcessEventAsync
しかし、このコードの文脈では全く重要ではありません)。
そして、結果を選択する2番目のSelect。これは、タスクが非同期ではなく、同期で実行されることを意味しませんか(無駄に労力がかかる)。それとも、タスクは非同期で実行され、それが完了したら残りのクエリが実行されるのでしょうか?
クエリがブロック化されているということです。ですから、実際には非同期ではありません。
分解してみる。
var inputs = events.Select(async ev => await ProcessEventAsync(ev))
は、まず各イベントに対して非同期処理を開始します。次にこの行。
.Select(t => t.Result)
は、それらの操作が一度に完了するのを待ちます (最初に最初のイベントの操作を待ち、次に次のイベントの操作を待ち、さらに次のイベントの操作を待つ、といった具合です)。
この部分は私が気にしない部分である。なぜなら、ブロックしてしまうし、例外が発生した場合、それを
AggregateException
.
と、このように完全に同じなのでしょうか?
var tasks = await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev)));
var inputs = tasks.Where(result => result != null).ToList();
var inputs = (await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev))))
.Where(result => result != null).ToList();
はい、この2つの例は等価です。どちらもすべての非同期オペレーションを開始します (
events.Select(...)
)、そしてすべての処理が任意の順序で完了するのを非同期に待ちます (
await Task.WhenAll(...)
)、そして残りの作業を進める(
Where...
).
これらの例は、いずれも元のコードとは異なっています。元のコードはブロック化されており、例外を
AggregateException
.
関連
-
[解決済み] LINQで複数の "order by "を使用する
-
[解決済み] async」と「await」の使い方とタイミング
-
[解決済み] SelectとSelectManyの違い
-
[解決済み] LINQのGroup by
-
[解決済み] DataTableに対するLINQクエリ
-
[解決済み] async/await関数を並列に呼び出す
-
[解決済み] async/await - タスクとvoidをいつ返すか?
-
[解決済み] C#でawaitを使わずに非同期メソッドを安全に呼び出す方法
-
[解決済み] await/asyncを使用しているときにHttpClient.GetAsync(...)が返らない
-
[解決済み] Task.Runをメソッドに入れないと非同期にはならないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] [Solved] 1つ以上のエンティティで検証に失敗しました。詳細は'EntityValidationErrors'プロパティを参照してください [重複]。
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】バックスラッシュを含むパス文字列のエスケープシーケンスが認識されない件
-
[解決済み】Unity 「関連するスクリプトを読み込むことができません」「Win32Exception: システムは指定されたファイルを見つけることができません"
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】パラメータ付きRedirectToAction
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み】Parallel.ForEachでawaitをネストする【重複あり