Reputation: 10035
My question is based on article Best Practices in Asynchronous Programming
So i have this code
async static void AsyncVersion()
{
Stopwatch sw = Stopwatch.StartNew();
string url1 = "http://rsdn.ru";
string url2 = "http://gotdotnet.ru";
string url3 = "http://blogs.msdn.com";
var webRequest1 = WebRequest.Create(url1);
Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
...
so this code throws exception, for example when i haven't inet connection. So when i'm following msdn's guidances and change signature of method to Task (instead of void), but after this it devour all exceptions, but hey aren't handle by external catch
block.
Entire code is below
using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication8
{
class Program
{
async static Task AsyncVersion()
{
Stopwatch sw = Stopwatch.StartNew();
string url1 = "http://rsdn.ru";
string url2 = "http://gotdotnet.ru";
string url3 = "http://blogs.msdn.com";
var webRequest1 = WebRequest.Create(url1);
Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse1 = await webRequest1.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url1,
webResponse1.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
var webRequest2 = WebRequest.Create(url2);
Console.WriteLine("Before webRequest2.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse2 = await webRequest2.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url2,
webResponse2.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
var webRequest3 = WebRequest.Create(url3);
Console.WriteLine("Before webRequest3.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse3 = await webRequest3.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url3,
webResponse3.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
}
static void Main(string[] args)
{
try
{
Console.WriteLine("Main thread id: {0}", Thread.CurrentThread.ManagedThreadId);
Task task = new Task(() => AsyncVersion());
task.Start();
Console.WriteLine("Right after AsyncVersion() method call");
//Ожидаем завершения асинхронной операции
task.Wait();
Console.WriteLine("Asyncronous task finished!");
}
catch (Exception e)
{
//Все исключения в TPL пробрасываются обернутые в AggregateException
Console.WriteLine("Exceptopn: {0}", e.Message);
}
Console.ReadLine();
}
}
}
old version:
using System;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication8
{
class Program
{
async static void AsyncVersion()
{
Stopwatch sw = Stopwatch.StartNew();
string url1 = "http://rsdn.ru";
string url2 = "http://gotdotnet.ru";
string url3 = "http://blogs.msdn.com";
var webRequest1 = WebRequest.Create(url1);
Console.WriteLine("Before webRequest1.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse1 = await webRequest1.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url1,
webResponse1.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
var webRequest2 = WebRequest.Create(url2);
Console.WriteLine("Before webRequest2.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse2 = await webRequest2.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url2,
webResponse2.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
var webRequest3 = WebRequest.Create(url3);
Console.WriteLine("Before webRequest3.GetResponseAsync(). Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
var webResponse3 = await webRequest3.GetResponseAsync();
Console.WriteLine("{0} : {1}, elapsed {2}ms. Thread Id: {3}", url3,
webResponse3.ContentLength, sw.ElapsedMilliseconds,
Thread.CurrentThread.ManagedThreadId);
}
static void Main(string[] args)
{
try
{
Console.WriteLine("Main thread id: {0}", Thread.CurrentThread.ManagedThreadId);
Task task = new Task(AsyncVersion);
task.Start();
Console.WriteLine("Right after AsyncVersion() method call");
//Ожидаем завершения асинхронной операции
task.Wait();
Console.WriteLine("Asyncronous task finished!");
}
catch (System.AggregateException e)
{
//Все исключения в TPL пробрасываются обернутые в AggregateException
Console.WriteLine("AggregateException: {0}", e.InnerException.Message);
}
Console.ReadLine();
}
}
}
Upvotes: 1
Views: 5570
Reputation: 245008
new Task(() => AsyncVersion())
This is the problematic part. The Task
constructor doesn't understand async
, so it ignores the Task
returned from AsyncVersion
. (The fact that you had to use lambda instead of writing AsyncVersion
directly should have alerted you that something weird is happening.)
You have several options how to fix this (best options last):
Use Task<Task>
and Wait()
for the inner Task
too:
Task<Task> task = new Task<Task>(AsyncVersion);
task.Start();
task.Result.Wait();
Use Unwrap()
to change the Task<Task>
to Task
that represents both Task
s:
Task<Task> task = new Task<Task>(AsyncVersion);
task.Start();
task.Unwrap().Wait();
Use Task.Run()
, which does understand async
:
Task task = Task.Run(() => AsyncVersion());
task.Wait();
Don't start a Task
at all, just call the async
method:
Task task = AsyncVersion();
task.Wait();
Upvotes: 10