Przeczytałem wiele artykułów wprowadzających na temat aktualizacji głównego interfejsu w wątku w tle, a większość z nich używa Control.Invoke i Control.BeginInvoke. To dobre rozwiązania, ale są dwa problemy:
1. Musisz odwołać się do System.Windows.Forms, a następnie użyć System.Windows.Forms
2. Struktura kodu jest stosunkowo chaotyczna. (Właściwie to też jest spowodowane przez #1)
Microsoft oferuje inne, bardziej eleganckie rozwiązanie, którym jest System.Threading. SynchronizationContext。 Jak widać, nie ma go w namesapce System.Windows.Forms, więc możemy go słusznie używać w BusinessLaryer, Controllerer, a nawet modułach.
I jest bardzo wygodny w użyciu, wystarczy skupić się na następujących dwóch metodach:
1. Wyślij: Wysyła żądanie aktualizacji interfejsu do głównego wątku, blokując bieżący wątek do czasu jego powrotu.
2. Post: Wysyła żądanie aktualizacji interfejsu do głównego wątku bez blokowania bieżącego wątku.
W rzeczywistości wszystkie są tą samą metodą, z tą różnicą, że wysyłanie jest synchroniczne, a postprodukcyjne asynchroniczne
Przed formą Form1 = nową Form1(), obiekt SynchronizationContext był pusty, a gdy formularz Form1 został utworzony, obiekt SynchronizationContext był dodawany do tego wątku. Odpowiedź jest taka, że gdy obiekt Control jest tworzony, obiekt SynchronizationContext jest również tworzony i dołączany do wątku. Wszystko to przy użyciu formy InitializeComponent(); Gdy to zostanie zrobione, może otrzymać obiekt, który nie jest NULL
Na koniec, różnica między metodami Sendt() i Post() w SynchronizationContext:
Send() jest realizowane przez proste wywołanie delegata na bieżącym wątku (wywołanie synchroniczne). Oznacza to, że wątek UI jest wywoływany bezpośrednio na podwątku, aby wykonać go, a podwątek będzie kontynuowany po zakończeniu wykonania wątku UI.
Post() jest realizowane przez wywołanie delegata na puli wątków (wywołanie asynchroniczne). Dzieje się tak, ponieważ podwątek znajdzie wątek z puli wątków, aby dostroić wątek UI, a podwątek bezpośrednio wykona własny kod, nie czekając na zakończenie wątku UI. Kod testowy:
Wynik:
Główny wątek UI: 1 Wątek: 5 SynchContext:1
Streszczenie:Obiekt SynchronizationContext w wątku UI, niezależnie od tego, czy jest wywoływany w głównym wątku, czy w wątku, będzie wykonywany na głównym wątku, więc gdy jest dużo czasochłonnego kodu, interfejs UI zawiesza się lub udaje śmierć!
W zasadzieWątek UI nie używa klasy SynchronizationContext, lecz WindowsFormsSynchronizationContextTen Dongdong.
Kod źródłowy System.Threading.SynchronizationContext:
Kod źródłowy WindowsFormsSynchronizationContext:
|