2017-01-19 8 views
0

次のコードを実行すると、HttpClient.GetAsync()呼び出しが完了してから結果が返される前にメッセージ"Press Enter to continue... "が表示されます。実際のイベントシーケンス:GetAsync()コールが行われ、 "Press Enter..."というメッセージが表示され、結果がコンソールウィンドウに1つずつ出力されます。 「Press Enter...」メッセージを表示する前に、すべてのGetAsync()コールが完了するまでどのように待つのですか? DownloadPageAsync以来すべてのタスクが完了するまで非同期コードを待機させる方法を教えてください。

class Program 
{ 
    static HttpClient client = new HttpClient(); 

    static void Main(string[] args) 
    { 
    RunAsync().Wait(); 

    Console.WriteLine("\n\n\n\nPress Enter to continue... "); 
    Console.ReadLine(); 
    } 

    static async Task RunAsync() 
    { 
    List<string> urls = new List<string>() 
    { 
     "http://www.domain1.com", 
     "http://www.domain2.com", 
     "http://www.domain3.com", 
     "http://www.domain4.com" 
    }; 

    foreach (var url in urls) 
    { 
     DownloadPageAsync(url); 
    } 
    } 

    static async Task<string> DownloadPageAsync(string url) 
    { 
    Console.WriteLine("Starting: " + url); 

    HttpResponseMessage response = await client.GetAsync(url); 

    if (response.IsSuccessStatusCode) 
    { 
     // do stuff here 
    } 

    Console.WriteLine("Done: " + url); 

    return response.Content.ToString(); 
    } 
} 

答えて

3

あなたはすべてのタスクのリストを作成し、それらのすべてを待つことができ、タスクを返します。

Task.WhenAll(urls.Select(url => DownloadPageAsync(url))) 

または簡略化:

Task.WhenAll(urls.Select(DownloadPageAsync)) 
+0

「Task.WhenAll(urls.Select(DownloadPageAsync))」に単純化できるメカニズムはありますか?私はそのフォーマットに遭遇したのは初めてです。 –

+0

'Select'は' Func 'を呼び出します。これは' DownloadPageAsync'が起こります。 –

+0

'RunAsync'から' async'キーワードを削除し、 'Task.WhenAll(...) 'を返すようにしてください。 – AndyPook

0

私は問題があることだと思いますRunAsync()メソッド内のDownloadPageAsyncメソッドを待機していません。あなたは以下のコードにRunAsync()方法を更新した場合、私はあなたが期待通りに動作します信じる:

static async Task RunAsync() 
{ 
    List<string> urls = new List<string>() 
    { 
     "http://www.domain1.com", 
     "http://www.domain2.com", 
     "http://www.domain3.com", 
     "http://www.domain4.com" 
    }; 

    foreach (var url in urls) 
    { 
     // added await here 
     await DownloadPageAsync(url); 
    } 
} 
-2

あなたは、すべてはあなたの例では、あなたがコードを実行し、待機していない、あなたが望む呼び出すごとに異なるタスクを作成する必要がありますコールのために。 WhenAllを呼び出すと、すべてのタスクが作成されます。コードを使用し、各MakeYouCallメソッドの内側にリストに項目を挿入するとします。そのリストは、ロックする必要がある共有リソースになります。 WhenAllが作成されると、結果を待たずに(Wait()を呼び出す)、コレクションが部分的に埋められます。その後

var register1 = new Action(() => MakeYourCall1()); 
var register2 = new Action(() => MakeYourCall2()); 
var register3 = new Action(() => MakeYourCall3()); 

その後、

var t1 = Task.Factory.StartNew(register1); 
var t2 = Task.Factory.StartNew(register2); 
var t3 = Task.Factory.StartNew(register3); 

あなたはそれを待って、タスクを返しますWhenAllを呼び出すことができます。あなたはかなりの要求が順次発生するだろう場合 がDownloadPageAsyncラインにawaitを追加...私のコメント

を参照してください、けれども

Task.WhenAll(t1, t2, t3).Wait(); 
1

@パトリック・ホフマンの答えは良いものです(アップ投票)。

RunAsyncasyncを使用しましたが、awaitがありません。したがって、それはタスクを返しますが、DownloadPageAsync呼び出しが完了するのを待っていません。つまり、このメソッドはただちに完了する「空の」タスクを返します。したがって、あなたの.Wait()は何も待っていません。

+0

のようなもの私はこの提案を試みましたが、次のURLの処理を開始する前に、DownloadPageAsync()が完了するまでforeachが一時停止するように見えます。あれは正しいですか? – DenaliHardtail

+0

が正しい。ここで 'await'を使用すると、すべての要求が順次発生します。あなたの 'RunAsync'メソッド内で定義されたすべてのリクエストを並行して実行したい場合は、@ partick-hofmanのようなものが必要です。説明のために – AndyPook

+0

がありがとうございます。私はこのアプローチを早い段階で試してみて、何が起こるかを見て待っていたと思う。 – DenaliHardtail

関連する問題