Дождаться завершения потока при закрытии окна консоли

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    internal class Program
    {
        [DllImport("Kernel32")]
        private static extern bool SetConsoleCtrlHandler(ConsoleClosedDelegate handler, bool add);
        private delegate bool ConsoleClosedDelegate(CtrlType ctrlType);

        private enum CtrlType
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT = 1,
            CTRL_CLOSE_EVENT = 2,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT = 6
        }

        private static bool _done = false;

        static void Main(string[] args)
        {
            SetConsoleCtrlHandler(OnConsoleClosed, true);

            Task task = Task.Run(() =>
            {
                for (int i = 0; i < 100; ++i)
                {
                    string t = $"Iteration {i + 1}";
                    Console.WriteLine(t);
                    System.Diagnostics.Debug.WriteLine(t);

                    Thread.Sleep(100);
                }

                _done = true;
            });
            task.Wait();

            System.Diagnostics.Debug.WriteLine("Main() is done");
        }

        private static bool OnConsoleClosed(CtrlType ctrlType)
        {
            if (!_done)
            {
                Console.WriteLine("Terminating...");
                System.Diagnostics.Debug.WriteLine("Terminating...");

                Task task = Task.Run(() =>
                {
                    while (!_done)
                    {
                        System.Diagnostics.Debug.WriteLine("Waiting 200ms...");
                        Thread.Sleep(200);
                    }
                });
                task.Wait();
            }

            System.Diagnostics.Debug.WriteLine("OnConsoleClosed is done");
            return true;
        }
    }
}

В целом, всё работает. События приходят. Но, как всегда, есть проблема.
В новых версиях винды в качестве консоли используется обёрточное (как я понимаю) окно, гордо называемое Terminal. Когда его закрываешь, вызывается обработчик OnConsoleClosed. Но через 1-3 секунд эта обёртка решает, что программа зависла и рубит процесс, не давая потоку завершиться. Возможно, в старой консоли код работал бы. Но проверить эту теорию мне сейчас не на чем :man_shrugging: А в новой винде переключение на старую консоль тупо перестало работать (хотя в настройках такая опция осталась) :man_with_turban:
А как проверить, программа сейчас запущена в старой консоли или в новом терминале? И что в коде написать, чтобы терминал не рубил процесс по таймауту после своего закрытия? :thinking:

Вчера вечером проверил на ноутбуке. Там стоит более старая версия винды, где переключение на старую консоль ещё работает. В старой консоли происходит то же самое. Консоль принудительно закрывается примерно через 3 секунды после нажатия на крестик, не дожидаясь завершения потока.
Можно с этим что-то сделать?

Напиши неконсольную программу-запускалку, и используй команду start. start запустит процесс, а неконсольная программа не создаст новое окно. Программа-запускалка запустит твою программу, и наверное тогда получится закрыть консоль без прекращения работы твоей программы.

Ещё можешь попробовать твою программу сервисом делать (у них там вроде было свойство “Interact with desktop”, но его усиленно выпиливали, не знаю как прогресс).

Сложна!
Лучше тогда на CTRL + C обработчик повесить. Когда гуглил, натыкался на такой вариант.

Ctrl+C тоже не катит. Нашёл два способа повесить обработчик, но они оба не катят.
Когда нажимаю Ctrl + C, консоль просто умирает. С обработчиком - через 1-2 секунды. Без него - сразу.
Причём, если обработчик есть - его код не выполняется. Даже System.Diagnostics.Debug.WriteLine("fuck"); ничего не выводит :man_shrugging: