简体   繁体   English

在异步任务中捕获异常

[英]Catch exception in async Task

I'm working in C# (console application). 我正在使用C#(控制台应用程序)。

In my program, I have to contact a httpClient. 在我的程序中,我必须联系httpClient。 First I check if the client is responding using GetAsync . 首先,我检查客户端是否使用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. 我添加了一个ContinueWith但是不起作用。 With a breackpoint I saw that the piece of code is reached at the start of my Task so the exception is always null. 有了breackpoint,我看到了在我的Task开始时到达了这段代码,因此异常始终为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. 假设您是针对.Net 4.5或更高版本运行此程序,则存在该异常,但它并未引起注意。

So, first of all, you should .Wait() for your task to complete so that the calling code has a chance to observe the exception. 因此,首先,您应该.Wait()完成任务,以便调用代码有机会观察异常。

Generally speaking, you should avoid using Task.Factory.StartNew() and prefer Task.Run() instead - see Stephen Toub's explanation why . 一般来说,您应该避免使用Task.Factory.StartNew()而应首选Task.Run() -请参阅Stephen Toub的why解释 But if you prefer to use Task.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. 但是,如果出于某种原因更喜欢使用Task.Factory.StartNew ,则还必须首先.Unwrap()原始任务,以获得想要获得结果的实际任务。 (Do note that .Unrwap() is an extension method that is available for Task<Task> but not Task , so type the original variable accordingly; ie, use var task = Task.Factory.StartNew(...) ) (请注意, .Unrwap()是可用于Task<Task>而不是Task的扩展方法,因此请相应地键入原始变量;即,使用var task = Task.Factory.StartNew(...)

ContinueWith will be executed when the Task completed, with or without success. 无论任务成功与否,都将在任务完成时执行ContinueWith

In the case of success, your tsk.Exception in ContinueWith will be null. 成功的情况下,ContinueWith中的tsk.Exception将为null。

Can you try : 你能试一下吗 :

.StartNew(...)
.ContinueWith(tsk =>
        {
            //thrown
        },TaskContinuationOptions.OnlyOnFaulted);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM