2014-11-04 40 views
2

我正在讀一些有關異步&等待的博客,特別是Scott's blog。我有一個下面的代碼示例,它可能會下載一個URL列表。爲了簡化事情並使時序合理和可重複,我用一個Task.Delay等待呼叫取代了真實的下載代碼。異步等待(再次)在lambda

第一個代碼在lambda表達式中沒有異步等待對,而第二個代碼沒有。這兩個代碼都可以編譯,並且兩個時間點都相同(約1秒)。

1.)哪種方法是正確的方法?

2.)lambda中的等待異步對會花費更多嗎?

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    // Capture the UI synchronization context for use later 
    var ui = TaskScheduler.FromCurrentSynchronizationContext(); 

    // sample 1 , is this the right way? 
    var items = Enumerable.Range(1, 100) 
    .Select(i => i.ToString()) 
    .ToList(); 

    var sp = new Stopwatch(); 
    sp.Start(); 

    // NO await async pair in lambda 
    var results1 = await Task.WhenAll(items.Select(item => DownloadFileAsync(item))); 

    sp.Stop(); 
    var testResult = string.Format("Single await: {0} seconds", sp.Elapsed.TotalSeconds); 

    // sample 2, or this way? 
    var items1 = Enumerable.Range(1, 100) 
    .Select(i => i.ToString()) 
    .ToList(); 

    var sp1 = new Stopwatch(); 
    sp1.Start(); 

    // WITH await async pair in lambda 
    var results = await Task.WhenAll(items1.Select(async item => await DownloadFileAsync(item))); 

    sp1.Stop(); 
    var testResult1 = string.Format("Double await: {0} seconds", sp1.Elapsed.TotalSeconds); 

    // show results 

    await Task.Factory.StartNew(() => 
    { 
     MessageBox.Show(testResult + System.Environment.NewLine + testResult1); 
    }, CancellationToken.None, TaskCreationOptions.None, ui).ConfigureAwait(false); 

} 

private async Task<string> DownloadFileAsync(string uri) 
{ 
    //using (var client = new WebClient()) 
    //{ 
    // string data = await client.DownloadStringTaskAsync(uri).ConfigureAwait(false); 
    // return data; 
    //} 

    await Task.Delay(1000).ConfigureAwait(false); 
    return uri; 


} 

回答

4

兩者大致相同。第一個效率稍高一點。

就此問題而言,您可以將await視爲「展開」任務,而將async視爲「包裝」任務中的方法。第一個示例使用lambda表達式來定義具有簽名Task<string> F(string)的函數。第二個例子定義的函數具有相同的簽名。不同之處在於第一個示例直接從DownloadFileAsync直接返回任務,而第二個示例解包任務並再次包裝它。

+0

有沒有另外一種方式來「直觀地」看到差異?例如。查看IL代碼? – alpinescrambler 2014-11-05 00:07:06

+0

@alpinescrambler:是;由編譯器生成的代碼是非常不同的。 – 2014-11-05 06:48:38