2014-11-04 2 views
2

비동기 &에 대한 몇 가지 블로그 (특히 Scott's blog)를 읽었습니다. 아래에 URL 샘플을 다운로드하는 코드 샘플이 있습니다. 일을 단순화하고 합리적이고 반복 가능한 타이밍을 만들기 위해 나는 실제 다운로드 코드를 Task로 교체했습니다 .Delay 기다리는 전화.비동기 람다에서 (비동기)

첫 번째 코드에는 람다 식 내부에 비동기 대기 쌍이없고 두 번째 코드에는 짝수 쌍이 없습니다. 두 코드가 모두 컴파일되고 두 타이밍이 모두 동일하게 출력됩니다 (약 1 초).

1) 어떤 방법으로 올바른 방법을 사용할 수 있습니까?

2.) 람다 내의 비동기 쌍을 기다리는 비용이 더 많이 들까 요?

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은 작업의 "래핑"으로 생각할 수 있습니다. 첫 번째 예제에서는 람다 식을 사용하여 Task<string> F(string)이라는 서명 함수를 정의합니다. 두 번째 예제에 정의 된 함수는 동일한 시그니처를가집니다. 차이점은 첫 번째 예제에서는 DownloadFileAsync에서 직접 작업을 반환하는 반면 두 번째 예제에서는 작업을 unwrap하고 다시 다시 랩핑한다는 점입니다.

+0

차이점을 "시각적으로"볼 수있는 다른 방법이 있습니까? 예 : IL 코드보기? – alpinescrambler

+0

@alpinescrambler : 예; 컴파일러에 의해 생성 된 코드는 매우 다릅니다. –