Поймать исключение в асинхронной задаче - PullRequest
0 голосов
/ 05 сентября 2018

Я работаю в C # (консольное приложение).

В моей программе мне нужно связаться с httpClient. Сначала я проверяю, отвечает ли клиент, используя GetAsync. Так что мой метод запроса - асинхронный, что делает мою задачу асинхронной.

Когда клиент не отвечает (или что-то еще), он генерирует исключение, но я не могу его поймать.

Я добавил ContinueWith, но он не работает. С помощью точки взлома я увидел, что кусок кода достигается в начале моей Задачи, поэтому исключение всегда равно null.

Как я могу решить эту проблему?

Вот мой код:

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

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Вы не ждете и не наблюдаете за результатом своей задачи. Предполагая, что вы работаете с .Net 4.5 или более поздней версией, исключение есть, но оно остается незамеченным.

Итак, прежде всего вам необходимо .Wait() завершить задачу, чтобы у вызывающего кода была возможность наблюдать исключение.

Вообще говоря, вам следует избегать использования Task.Factory.StartNew() и предпочитать вместо него Task.Run() - см. объяснение Стивена Туба, почему . Но если вы предпочитаете использовать Task.Factory.StartNew по какой-либо причине, вам дополнительно необходимо сначала .Unwrap() исходное задание, чтобы получить фактическое задание, для которого вы хотите получить результат. (Обратите внимание, что .Unrwap() - это метод расширения, который доступен для Task<Task>, но не для Task, поэтому введите исходную переменную соответственно; то есть используйте var task = Task.Factory.StartNew(...))

0 голосов
/ 05 сентября 2018

ContinueWith будет выполнено, когда задание выполнено, с успехом или без.

В случае успеха ваш tsk.Exception в ContinueWith будет нулевым.

Можете ли вы попробовать:

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