Informacje o bezpieczeństwie wątków GDI w systemie Windows, see this reference article.
To wyraźnie wskazuje, że może dostęp bezpiecznie uchwyty z wielu wątków, ale, że nie powinno być wykonane w tym samym czasie. Musisz chronić dostęp do uchwytów GDI, np. używanie krytycznych sekcji.
Pamiętaj, że GDI uchwyty, podobnie jak większość obsługuje Windows są wskaźniki struktur wewnętrznych odwzorowanych do integer
(NativeUInt
pod nowszym Windows dla 64-bitowej kompatybilności). Podobnie jak w przypadku wielu wątków, równoczesny dostęp do tej samej treści może być źródłem problemów, które są bardzo trudne do zidentyfikowania i naprawienia.
Część interfejsu użytkownika samego VCL nigdy nie miała być bezpieczna dla wątków od samego początku, ponieważ opierała się na nie-wątkowym Windows API. Na przykład, jeśli zwolnisz obiekt GDI w wątku, który nadal jest potrzebny w innym wątku, staniesz przed potencjalnym GPF.
Embarcadero (w tym czasie) mógł utworzyć wątek bezpieczny dla VCL, szeregując dostęp do wszystkich interfejsów przez krytyczne sekcje, ale może mieć dodatkową złożoność i zmniejszyć ogólną wydajność. Zauważ, że nawet platforma Microsoft .Net (zarówno w wersji WinForms, jak i WPF) wymaga również dedykowanego wątku do dostępu do interfejsu użytkownika, AFAIK.
Tak więc, aby odświeżyć interfejs z wielu wątków, masz kilka wzorów:
- Zastosowanie
Synchronize
połączenia z gwintem;
- Wysyła niestandardową wiadomość GDI (patrz
WM_USER
) z wątków działających w tle, aby powiadomić wątek interfejsu użytkownika, że potrzebne jest odświeżenie;
- Podejście bezpaństwowe: interfejs będzie odświeżał zawartość od czasu do czasu, z poziomu logiki (za pomocą licznika czasu lub po naciśnięciu niektórych przycisków, które mogą zmienić dane).
Z mojego punktu widzenia preferuję opcję 2 dla większości interfejsów użytkownika i dodatkową opcję 3 (którą można łączyć z opcją 2) w celu zdalnego dostępu klienta do serwera. Dlatego nie musisz chcieć od strony serwera, aby wywołać pewne zdarzenie aktualizacji w interfejsie użytkownika. W świecie HTTP/AJAX RESTful ma to zdecydowanie sens. Opcja 1 jest nieco powolna, IMHO.We wszystkich przypadkach opcje 2 i 3 oczekują wyraźnego n-Tier layered architecture, w którym logika i interfejs użytkownika nie są mieszane, ale mimo to jest to dobry wzór do naśladowania dla każdego poważnego rozwoju.
Było trochę wyjaśnienia w [docs] (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/threadsusingthemainvclthread_xml.html). Jakoś nie mogę znaleźć czegoś podobnego w obecnej [dokumentacji] (http://docwiki.embarcadero.com/RADStudio/en/How_To_Build_Multithreaded_Applications). –