I'm working in C# (console application).
In my program, I have to contact a httpClient. First I check if the client is responding using GetAsync
. So my request method is async, making my Task async.
When client doesn't respond (or something else) it throw an exception but i'm unable to catch it.
I added a ContinueWith
but it doesn't work. With a breackpoint I saw that the piece of code is reached at the start of my Task so the exception is always null.
How can I solve this problem ?
There is my code :
static void Run()
{
String urlRequest = "";
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Console.WriteLine($"Program running, press a key to stop");
try
{
Task task = Task.Factory.StartNew(async () =>
{
using (HttpClientHandler handler = new HttpClientHandler { Credentials = new NetworkCredential("user", "pass") })
{
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(urlRequest);
client.DefaultRequestHeaders.Accept.Clear();
bool serviceAvailable = await CheckService(client);
if (serviceAvailable)
{
bool doLoop = true;
while (doLoop)
{
// Do something
Thread.Sleep(100);
if (ct.IsCancellationRequested)
{
Console.WriteLine("\r\ntask cancelled");
break;
}
}
}
else
{
throw new HttpRequestException($"Unable to contact service at {urlRequest}");
}
}
}, ct).ContinueWith(tsk =>
{
if (tsk.Exception != null)
throw tsk.Exception;
});
Console.ReadKey();
cts.Cancel();
Thread.Sleep(1000);
}
catch (Exception e)
{
Log(e);
}
}
static async Task<bool> CheckClient(HttpClient client)
{
Console.WriteLine("Check service Call ...");
HttpResponseMessage response = await client.GetAsync("CheckService");
if (response.IsSuccessStatusCode)
{
return true;
}
return false;
}
You are neither waiting for nor observing the result of your task. Assuming that you're running this against .Net 4.5 or later, the exception is there but it is going unnoticed.
So, first of all, you should
.Wait()
for your task to complete so that the calling code has a chance to observe the exception.Generally speaking, you should avoid using
Task.Factory.StartNew()
and preferTask.Run()
instead - see Stephen Toub's explanation why. But if you prefer to useTask.Factory.StartNew
for whatever reason, then you additionally must first.Unwrap()
the original task to obtain the actual task for which you want the result. (Do note that.Unrwap()
is an extension method that is available forTask<Task>
but notTask
, so type the original variable accordingly; i.e., usevar task = Task.Factory.StartNew(...)
)ContinueWith will be executed when the Task completed, with or without success.
In the case of success, your
tsk.Exception
in ContinueWith will be null.Can you try :