首页 > 解决方案 > 在异步任务中捕获异常

问题描述

我正在使用 C#(控制台应用程序)。

在我的程序中,我必须联系 httpClient。首先,我检查客户端是否使用GetAsync. 所以我的请求方法是异步的,使我的任务异步。

当客户端没有响应(或其他)时,它会引发异常,但我无法捕捉到它。

我添加了一个ContinueWith,但它不起作用。通过一个断点,我看到在我的任务开始时到达了这段代码,因此异常始终为空。

我怎么解决这个问题 ?

有我的代码:

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;
}

标签: c#multithreadingtask

解决方案


您既不等待也不观察任务的结果。假设您针对 .Net 4.5 或更高版本运行此程序,则存在异常,但不会引起注意。

因此,首先,您应该.Wait()为您的任务完成,以便调用代码有机会观察到异常。

一般来说,您应该避免使用Task.Factory.StartNew()并更喜欢Task.Run()- 请参阅Stephen Toub 的解释为什么Task.Factory.StartNew但是,如果您出于某种原因更喜欢使用,那么您还必须首先.Unwrap()获取原始任务才能获得您想要结果的实际任务。(请注意,这.Unrwap()是一种可用于Task<Task>但不可用于的扩展方法Task,因此请相应地键入原始变量;即,使用var task = Task.Factory.StartNew(...)


推荐阅读