Задать вопрос
@espaaaaa

Как работает TaskCompletionSource, когда возникает исключение?

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



public class Program
{
    public static Task Start()
    {
        TaskCompletionSource taskCompletionSource = new();

        Process process = new()
        {
            StartInfo = new ProcessStartInfo(@"program.exe"),
            EnableRaisingEvents = true,
        };
        process.Exited += (object? sender, EventArgs args) =>
        {
            Console.WriteLine("Процесс завершен");
            try
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                taskCompletionSource.SetResult();
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            }
            catch
            {

                Console.WriteLine("Ошибка!");
            }
            Console.WriteLine("Событие завершено");
         

        };
        process.Start();

        return taskCompletionSource.Task;
    }
    public static async Task Main(string[] args)
    {

        await Start();

        Console.WriteLine("Выполняется продолжение");
        throw new Exception();

    }
}


Написал простой код, который ждет завершение процесса, использовал для этого TaskCompletionSource. Я использую консольное приложение, поэтому контекста синхронизации нет.

Как известно, SetResult запускает код (после await Start()) синхронно в потоке который обрабатывал событие (так как я не использую TaskCreationOptions.RunContinuationsAsynchronously).

В этом продолжении кода мы вызываем исключение
1) Почему его не перехватывает наш try catch, почему исключение не может найти блок catch когда раскручивает стек?
2) Почему оба вывода
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

Одинаковы, ведь по сути, поток после вызова SetResult падает, но каким то образом он выполняет код после SetResult
3) Если происходит упаковка исключения в Task, то в какой момент мы await-им этот task, чтобы наше исключение было выброшено?

Заранее спасибо
  • Вопрос задан
  • 50 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 1
@mvv-rus
Настоящий админ AD и ненастоящий программист
1) Насколько я вижу, вы запускаете другой процесс и устанавливаете обработчик события его завершения. А затем - вызываете необрабатываемое исключение в исходном процессе. Как вы его собираетесь перехватывать? Подсказка: чтобы смотреть что в каком процессе существует, выводите в печати на консоль свойство Id процесса. Текущий процесс, кстати, можно получит статическим методом Process.GetCurrentProcess,
2) Необработанное исключение само по себе не вызывает завершение процесса с точки зрения ОС. Исключение перехватывается где-то в коде среды выполнения, как необработанное. Где именно - смотрите ее исходный код, он доступен.
3) Исключение вызывается в момент любого ожидания завершения задачи: Wait, await, GetResult...
Но вам это тут ни к чему - никакого исключения у вас в этом Task не выбрасывается. Чтобы выбросить исключение в контексте задачи, на которую указывает свойство Task объекта класса TaskCompletionSource, надо использовать метод SetException этого объекта.
4) Вы желаете странного. Зачем?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы