【问题标题】:async await (again) inside lambdalambda 中的异步等待(再次)
【发布时间】:2014-12-30 21:32:27
【问题描述】:

我正在阅读一些关于 async 和 await 的博客,尤其是 Scott's blog 的博客。我在下面有一个代码示例,它可能会下载一个 URL 列表。为了简化事情并使时间安排合理且可重复,我用 Task.Delay 等待调用替换了真正的下载代码。

第一个代码在 lambda 表达式中没有 async-await 对,而第二个代码有。两个代码都编译,两个时间都一样(大约 1 秒)。

1.) 哪种方法是正确的方法?

2.) lambda 中的 await 异步对是否会花费更多?

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;


}

【问题讨论】:

    标签: task-parallel-library async-await c#-5.0


    【解决方案1】:

    两者大致相等。第一个效率更高。

    就本问题而言,您可以将await 视为“解包”任务,将async 视为“包装”任务中的方法。第一个示例使用 lambda 表达式定义签名为 Task&lt;string&gt; F(string) 的函数。第二个示例定义的函数具有相同的签名。不同之处在于,第一个示例直接从DownloadFileAsync 返回任务,而第二个示例将任务解包然后再次包装。

    【讨论】:

    • 是否有另一种方法可以“直观地”看到差异?例如。查看 IL 代码?
    • @alpinescrambler:是的;编译器生成的代码差别很大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多