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 секунд эта обёртка решает, что программа зависла и рубит процесс, не давая потоку завершиться. Возможно, в старой консоли код работал бы. Но проверить эту теорию мне сейчас не на чем 
 А в новой винде переключение на старую консоль тупо перестало работать (хотя в настройках такая опция осталась) ![]()
А как проверить, программа сейчас запущена в старой консоли или в новом терминале? И что в коде написать, чтобы терминал не рубил процесс по таймауту после своего закрытия? ![]()