Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async await (again) inside lambda

I was reading a few blogs about async & await, particularly that of Scott's blog . I have a code sample below, which presumably downloads a list of URLs. To simplify things and make the timings reasonable and repeatable, I replaced the real download code with a Task.Delay awaitable call.

The first code doesn't have an async-await pair inside the lambda expression, while the second one has. Both codes compile, and both timings come out the same (around 1 second).

1.) Which method is the right way to do this?

2.) Will the await async pair inside the lambda cost more?

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);    
}

and

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;        
}

like image 215
alpinescrambler Avatar asked Jan 17 '26 02:01

alpinescrambler


1 Answers

Both of them are roughly equivalent. The first one is slightly more efficient.

For the purposes of this question, you can think of

  • await as "unwrapping" a task, and
  • async as "wrapping" a method in a task.

The first example uses a lambda expression to define a function with the signature Task<string> F(string). The function defined by the second example has the same signature. The difference is that

  • the first example just returns the task from DownloadFileAsync directly
  • while the second example unwraps the task and then wraps it again.
like image 97
Stephen Cleary Avatar answered Jan 19 '26 18:01

Stephen Cleary



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!