Jestem w trakcie pisania aplikacji, która ma za zadanie dodać funkcjonalność do już istniejącej. Moja aplikacja żadnego UI nie ma, ale dodaje przyciski do oryginalnej, wszystko w czystym WinAPI. Po utworzeniu przycisku, kolejka komunikatów w naszym wątku zacznie się wypełniać, żebyśmy mogli obsłużyć zdarzenia, np. kliknięcie. I stąd, tworzę sobie nowy wątek, który najpierw utworzy odpowiednie kontrolki i wejdzie w message loop. Wszystko działa w porządku, ale gdy aplikacja zostanie zamknięta, chciałbym zatrzymać wątek, bo żadnych komunikatów i tak i tak otrzymywać nie będzie.
Wątek wygląda tak:

messageLoop = new Thread((ThreadStart)delegate
{
    CreateButton(0, 0);

    while (running)
    {
        Win32.MSG message;
        if (Win32.GetMessage(out message, IntPtr.Zero, 0, 0))
        {
            /* obsługa zdarzenia */

            Win32.TranslateMessage(ref message);
            Win32.DispatchMessage(ref message);
        }
    }
});

I teraz, by zatrzymać wątek, do głowy przyszły mi następujące opcje:

  1. Ustawić messageLoop.BackgroundThread = true i nie przejmować się wątkiem, który zakończy się, gdy moja aplikacja przestanie działać,
  2. W zdarzeniu process.Exited wywołać messageLoop.Abort() i złapać wyjątek - co w naszym przypadku nie zadziała w ogóle, bo wątek musi być w stanie WaitSleepJoin, co dzieje się co jakiś czas automatycznie, jednak nie wtedy, gdy wywołana jest blokująca funkcja poprzez P/Invoke.
  3. W zdarzeniu j/w ustawić running = false i wysłać do wątku komunikat poprzez PostThreadMessage, który spowoduje kolejną iterację i wyjście z pętli (mój przycisk jedyne co otrzyma to WM_PAINT przed wyjściem z aplikacji i wywołaniem zdarzenia w mojej aplikacji). Tutaj problem jest taki, że wątek w .NET to nie do końca to samo, co wątek w Windows i wcale nie jest pewne, że np. natywne id wątku nie może się nagle zmienić, "bo tak". Teoretycznie można te id uzyskać, przez jakże wiele nam mówiące prywatne pole o nazwie "DONT_USE_InternalThread".
  4. Zamienić GetMessage na PeekMessage i bawić się w Thread.Sleep, a tego typu sztuczek stosować nie lubię.

Także - czy jest jakaś inna metoda, która lepiej się nada w tej sytuacji?