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:
- Ustawić messageLoop.BackgroundThread = true i nie przejmować się wątkiem, który zakończy się, gdy moja aplikacja przestanie działać,
- 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.
- 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".
- 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?