A melhor forma de ver a grande diferença que o async faz é usando exemplos. Saindo de um código não só maior, mas muito mais complicado, com callbacks, tratamento de contexto e thread de execução, tratamento de erros aninhados com os callbacks, pra um código simples, como se fosse um código síncrono comum.
Código Antigo:
void ShowStuff()
{
var client = new WebClient();
var content = JsonValue.Parse(client.DownloadString("http://api.worldbank.org/countries?format=json&per_page=50"));
int number_of_countries = content[0]["total"];
int done = 0, error = 0;
InvokeOnMainThread(() =>
{
CountriesLabel.Text = string.Format("Countries: {0} done: 0 error: 0", number_of_countries);
});
foreach (JsonObject c in content[1])
{
string country_url = string.Format("http://api.worldbank.org/countries/{0}/indicators/NY.GDP.MKTP.CD&format=json", (string)c["id"]);
JsonValue json = null;
try
{
json = JsonValue.Parse(client.DownloadString(country_url));
}
catch (Exception e)
{
++error;
InvokeOnMainThread(() => status.Text = "Got exception " + e);
continue;
}
ThreadPool.QueueUserWorkItem(delegate
{
Map map = null;
try
{
map = LoadCountryLogo(c["name"]).Result;
}
catch (Exception e)
{
++error;
InvokeOnMainThread(() => status.Text = "Got exception " + e);
}
if (map != null)
{
ThreadPool.QueueUserWorkItem(delegate
{
Position position = null;
try
{
position = LookupCountryPosition(c["longitude"], c["latitude"]).Result;
if (position != null)
InvokeOnMainThread(() =>
{
AddPin(map, position);
++done;
status.Text = json["name"];
});
}
catch (Exception e)
{
error++;
InvokeOnMainThread(() => status.Text = "Got exception " + e);
}
});
}
});
InvokeOnMainThread(() => CountriesLabel.Text = string.Format("Countries: {0} done: {1} error: {2}", number_of_countries, done, error));
}
InvokeOnMainThread(() =>
{
CountriesLabel.Text = string.Format("Countries: {0}", number_of_countries);
});
}
Código usando C# 5.0:
async Task ShowStuffAsync()
{
var client = new HttpClient();
var content = JsonValue.Parse(await client.GetStringAsync("http://api.worldbank.org/countries?format=json"));
int number_of_countries = content[0]["per_page"];
int done = 0, error = 0;
CountriesLabel.Text = string.Format("Countries: {0} done: 0 error: 0", number_of_countries);
foreach (JsonObject c in content[1])
{
try
{
string country_url = string.Format("http://api.worldbank.org/countries/{0}/indicators/NY.GDP.MKTP.CD&format=json", (string)c["id"]);
var json = JsonValue.Parse(await client.GetStringAsync(country_url));
var map = await LoadCountryLogoAsync(json["name"]);
if (map != null)
{
var position = await LookupCountryPositionAsync(c["longitude"], c["latitude"]);
if (position != null)
{
AddPin(map, position);
status.Text = json["name"];
++done;
}
}
}
catch (Exception e)
{
++error;
status.Text = "Got exception " + e;
}
CountriesLabel.Text = string.Format("Countries: {0} done: {1} error: {2}", number_of_countries, done, error);
}
CountriesLabel.Text = string.Format("Countries: {0}", number_of_countries);
}