Исключение в задаче, не вызывающей сбой приложения - PullRequest
2 голосов
/ 24 апреля 2019

Я новичок в Task Parallel Library.Я знаю, что исключения в приоритетном и фоновом потоках работают одинаково, т.е. они распространяются в основной поток и приводят к аварийному завершению приложения (если не обрабатываются).Но я вижу другое поведение при использовании задач.Когда в Задаче возникает исключение, оно просто завершает свое выполнение, не прерывая работу приложения или других задач.Если я не ошибаюсь, Задача использует фоновый поток, поэтому исключение должно распространяться на Основной поток и аварийно завершать работу, как обычный Фоновый поток.

public static void Foo()
{
  throw new Exception("Blahh");
}
static void Main()
{
   Task t = Task.Run(()=>Foo());
   Thread.Sleep(500);
   Console.WriteLine("Main");
}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2019

Вы должны Wait() ваш Task. Если у задачи есть результат, можно получить доступ к свойству Result, которое вызывает Wait(). Обратите внимание, что исключение будет AggregateException, а исходные исключения будут в его коллекции InnerExceptions.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static void Main()
        {
            Example1();
            Example2();
            Thread.Sleep(500);
            Console.WriteLine("Main");
        }

        public static void Example1()
        {
            try
            {
                Console.WriteLine("Example1");
                Task t = Task.Run(() => Foo());
                t.Wait();
            }
            catch (AggregateException e)
            {
                foreach (var ex in e.InnerExceptions)
                    Console.WriteLine(ex.Message);
            }
        }

        public static void Example2()
        {
            try
            {
                Console.WriteLine("Example2");
                Task<string> t = Task.Run(() => { Foo(); return "Task result"; });
                string result = t.Result;
                Console.Write(result);
            }
            catch (AggregateException e)
            {
                foreach (var ex in e.InnerExceptions)
                    Console.WriteLine(ex.Message);
            }
        }

        public static void Foo()
        {
            throw new Exception("Blahh Exception");
        }
    }
}
1 голос
/ 24 апреля 2019

Вы должны изменить код на

public static void Foo()
{
  throw new Exception("Blahh");
}
static async Task Main()
{
   Task t = Task.Run(()=>Foo());
   Thread.Sleep(500);

   await t;

   Console.WriteLine("Main");
}

Что вы делаете сейчас, так это запускаете задачу «забей и забудь». Так что вы на самом деле говорите, мне плевать на результат (даже исключение).

Когда вы await задаете, вы говорите, что хотите знать результат задания. В этом случае вы делаете это, чтобы узнать, успешно ли выполнено задание (или возникло исключение).

Взгляните на это: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/await#exceptions

...