2017-11-02 9 views
0

あるソースからデータを取り込んで処理してから別のソースに保存するコードに取り組んでいます。両端で高レベルのレイテンシがあるため、私はasync/awaitを使用してロードと保存操作の両方が完了するのを待つことを試みています。理想的には、これはすべての入力タスクを開始し、各タスクが完了するとすぐに処理を行い、出力タスクを開始します.Task.WaitAllを使用すると、新しいタスクが開始されたときにプログラムが何もしなくなります。他のタスクリストをブロックせずにタスクリストを待つ

第2の非同期タスクは最初の結果に依存するため、最初の待ち状態から他の結果の処理を再開できるように2番目の待ち状態を処理する方法を理解することはできません。 2番目の待機時間に達すると、他の結果を処理するために再開する代わりに、保存機能が完了するまで完全にブロックされます。私はこのようなことをしようとしている、何が間違っている?その後、

async Task MainAsync() 
{ 
    /* gets a list of id's */ 

    var dataRequests = ids.Select(id => LoadEntryById(id)).ToList(); 

    foreach(var request in dataRequests) 
    { 
     RawEntry response = await request; 

     ProcessedEntry result = doSomething(response); 

     await SaveResult(result); 
    } 
} 

async Task<RawEntry> LoadEntryById(int id) 
{ 
    /* IO task */ 
} 

async Task SaveResult(ProcessedEntry result) 
{ 
    /* IO task */ 
} 
+0

SaveResultを待っていませんか?代わりにそれをリストに入れて、最後にそれらをすべて待ってください。 – Evk

+2

リクエストが既に定義されていて、そのデータを持っているので、 "リクエストを待つ"理由はありません。 5行目はその時点のすべてのデータを取得し、リストにロードします。 foreachはリストから個々の項目を取得します。 –

+0

@ John Rasch - 私は非同期のものについては専門家ではありませんが、現在、LoadEntryById ... ToList()が完了するまではforeachには到達しません。その点までのコードは同期的です。最初の 'await'は5行目にあり、ToListAsync()を使用している必要があります。 –

答えて

3

の代わりに、単一の方法に待っている、あなたの継続を使ってList<Task>を作成し、Task.WhenAllを使用します。

var tasks = ids.Select(async id => { 
    var response = await LoadEntryById(id); 
    var result = doSomething(response); 
    await SaveResult(result); 
}).ToList(); 

await Task.WhenAll(tasks); 

これは、非同期的にすべてのあなたのタスクを処理します。このセットアップLoadEntryById

Parallel.Foreach(ids.Select(id => LoadEntryById(id)), (rawEntry) => { 
    var result = doSomething(rawEntry); 

    await SaveResult(result); 
} 

RawEntry LoadEntryById(int id) 
{ 
    /* IO task */ 
} 

async Task SaveResult(ProcessedEntry result) 
{ 
    /* IO task */ 
} 

タスクを返却する必要はありませんが、それはやっているいただきました、それは異なります。

-1

私が正しくあなたを理解していれば、あなたはこれを試みることができます。

関連する問題