Задать вопрос
@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, чтобы наше исключение было выброшено?

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

Ничего подобного. SetResult завершает ожидание. А не то что код после await будет внутри SetResult.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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