I'm new to c# 5's async feature. I'm trying to understand the difference between these two implementations:
Implementation 1:
private void Start()
{
foreach(var url in urls)
{
ParseHtml(url);
}
}
private async void ParseHtml(string url)
{
var query = BuildQuery(url); //BuildQuery is some helper method
var html = await DownloadHtml(query);
//...
MyType parsedItem = ParseHtml(html);
SaveTypeToDB(parsedItem);
}
private async Task<string> DownloadHtml(string query)
{
using (var client = new HttpClient())
try
{
var response = await client.GetAsync(query);
return (await response.Content.ReadAsAsync<string>());
}
catch (Exception ex)
{
Logger.Error(msg, ex);
return null;
}
}
Implementation 2:
private void DoLoop()
{
foreach(var url in urls)
{
Start(url);
}
}
private async void Start(url)
{
await Task.Run( () => ParseHtml(url)) ;
}
private void ParseHtml(string url)
{
var query = BuildQuery(url); //BuildQuery is some helper method
var html = DownloadHtml(query);
//...
MyType parsedItem = ParseHtml(html);
SaveTypeToDB(parsedItem);
}
private string DownloadHtml(string query)
{
using (var client = new WebClient())
{
try
{
return client.DownloadString(query);
}
catch (Exception ex)
{
Logger.Error(msg, ex);
return null;
}
}
}
I'd rather use the second implementation as it will require less 'async' signatures on methods in my code. I'm trying to understand what's the benefit of using the HttpClient class vs using a new Task and awaiting it instead?
Is there any difference between the two implementations?
Async methods are intended to be non-blocking operations. An await expression in an async method doesn't block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.
GetAsync(Uri, HttpCompletionOption) Send a GET request to the specified Uri with an HTTP completion option as an asynchronous operation. GetAsync(Uri, CancellationToken) Send a GET request to the specified Uri with a cancellation token as an asynchronous operation.
The HTTP request is sent out, and HttpClient. GetAsync returns an uncompleted Task .
C# Language Async-Await Async/await will only improve performance if it allows the machine to do additional work.
For server applications, async
is about minimizing the number of blocked threads you've got: increasing the efficiency of the thread pool and perhaps allowing your program to scale to more users.
For client applications where you're unlikely to need to care about thread count, async
provides a relatively easy way to keep your UI running fluid when you perform I/O.
It is much different from Task.Run
underneath the hood.
I'd rather use the second implementation as it will require less 'async' signatures on methods in my code.
That sounds like a very odd justification. You're trying to execute fundamentally "somewhat asynchronously" - so why not make that clear?
Is there any difference between the two implementations?
Absolutely. The second implementation will tie up a thread while WebClient.DownloadString
blocks, waiting for the request to complete. The first version doesn't have any blocked threads - it relies on a continuation to fire when the request finishes.
Additionally, consider your Logger.Error
call. In the async version, that will still execute in the context of the original calling code. So if this is in, say, a Windows Forms UI, you'll still be on the UI thread, and you can access UI elements etc. In the second version, you'll be executing in a thread pool thread, and would need to marshal back to the UI thread to update the UI.
Note that your async void
method almost certainly shouldn't be async void
. You should only make an async
method return void
for the sake of complying with event handler signatures. In all other cases, return Task
- that way the caller can see when your task has finished, handle exceptions etc.
Also note that you don't need to use HttpClient
for asynchrony - you could use WebClient.DownloadStringTaskAsync
instead, so your final method could become:
private async Task<string> DownloadHtmlAsync(string query)
{
using (var client = new WebClient())
{
try
{
return await client.DownloadStringTaskAsync(query);
}
catch (Exception ex)
{
Logger.Error(msg, ex);
return null;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With