Czy Win32 jest thread-safe?

0

Hm, no właśnie - pytanie jak w temacie. Czy wyołania funkcji z Winapi z wątku są bezpieczne? Mam tu na myśli jeden wątek, który robi coś w tle i jednoczesnie bezpośrednio cos zmienia w oknie dialogowym utworzonym w innym wątku (np uaktualnia pasek postępu, zmienia etykietę, wyświetla komunikaty MessageBox lub tworzy inne okna). Albo tak sytuacja, że np. okno z progress barem zostanie bezpośrednio utworzone w drugim wątku i zmieniane bezpośrednio przez ten wątek.

Z moich testów wynika, że rzeczywiście cos takiego dziala i nic zlego się nie dzieje. Jednak szukając po necie natrafiłem na sprzeczne informacje - jedni twierdzą, że funkcje takie jak CreatDialog, DialogBox, SetDlgItemText itd są zawsze thread-safe, inni mówią że nie.

Jak to wygląda wg was? Wiem że technologia z porzedniej ery, ale czasami jeszcze mam do czynienia z takimi rzeczami. Nie mówie tu o przypadku, gdy trzeba synchronizować między sobą kilka wątków, a o tworzeniu, wyświetlaniu i zmienianiu okien w drugim wątku (poprzez użycie DialogBox, więc nie jest to tworznie obiektów klas)

0

Co do technologi z poprzedniej ery to bym sie klocil, jest to po prostu bardzo nisko zawieszona technologia i wszystko co wyswietla okno z niej korzysta.

Zauwaz, ze WinAPI (jesli chodzi o okienka) oparte jest o komunikaty systemowe i to system decyduje jak je pokolejkowac.
I tak chcac zmienic cos w progressbar wysylasz komunikat (SendMessage - lub wrapery w stylu SetDlgItem) oznaczajac okno uchwytem potem system go bierze i wysyla do okna progressbar. Gdzie moze nie byc thread safe ano standardowo odwolanie do uchwytu (zmiennej trzymajacej uchwyt) musi byc thread safe tak pierwsze co bylo wywolane (i skonczone) to tworzenie okna (podobnie ze zniszczeniem okna).

Druga sprawa to przekazywanie obiektow miedzy watkami, jak wyslesz uchwyt do bitmapy do jakiegos okna to musi on byc poprawny (a nie, ze cos z nia robisz w trakcie).

Co do MessageBox po prostu zablokuje watek.

No ale to o oknach a winapi to nie tylko to, jesli chodzi o zapis do pliku/rejestru/pamieci ... to obowiazuja takie zasady jak wszedzie - trzeba synchronizowac watki aby sobie krzywdy nie zrobily.

0

jeśli chodzi o SendMessage, jest synchronizacja między wątkami {i to dosyć nietypowa} (właśnie dlatego trzeba wołać SendMessage, żeby wykonać jakiś komunikat okna, a nie CallWindowProc, czy bezpośrednio calnąć procke okna co by było o niebo szybsze)

kiedyś myślałem, że SendMessage po prostu szuka procedurki okna po podanym hwnd i ją bezpośrednio woła (czyli opcja bez synchronizacji), od czasu kiedy wykonałem zakleszczenie funkcją GetWindowText wiem, że działanie jest ciut bardziej złożone...
zakleszczenie polegało na tym, że miałem wątek główny pompujący komunikaty i z nim związane okno, wątek poboczny coś tam robił... w pewnym momencie zawieszałem wątek główny a pracował wątek poboczny i teraz jeśli w takim wątku pobocznym wywołać SendMessage dla okna związanego z wątkiem głównym jest zakleszczenie...
dlaczego? bo SendMessage zatrzymuje działanie wątku(o ile jest w innym) i każe przetworzyć komunikat w wątku związanym z oknem, czyli de facto wszystkie komunikaty związane z oknem zostaną zawsze przetworzone w wątku tego okna, nawet gdy SendMessage (czy tam GetWindowText,itp. bo to i tak wszystko wrappery na SendMessage z odpowiednim komunikatem) zostanie wywołane w innym wątku niezwiązanym z oknem, więc jakiś mechanizm synchronizacji jest...
nie wiem dokładnie jak odbywa się przetwarzanie takich komunikatów z osobnych wątków, czy taki komunikat przechodzi pełny obieg w pętli, czyli GetMessage+DispatchMessage (tzn że w pętli wątku okna będzie widać przetwarzanie tego komunikatu wołanego z innego wątku), czy też GetMessage wewnętrznie potajemnie przetworzy taki komunikat, nigdy tego nie sprawdzałem (prawdopodobnie jest opcja 1)
w tym miejscu można zwrócić uwagę na fakt, że SendMessage tak naprawdę na sporo do roboty, bo najpierw musi określić czy wołane jest w wątku okna, czy zewnętrznego, jeśli okna, to pewnie bezpośrednio woła procedurkę okna, natomiast jeśli z innego musi poczekać na cykl pętli w wątku okna, więc na pierwszy rzut oka widać, że wywoływanie SendMessage z zewnętrznego wątku będzie miało dodatkowy narzut czasowy związanego z tą synchronizacją, tym większy im bardziej obciążony jest wątek pompujący komunikaty (dłuższe oczekiwanie na cykl pętli)

teraz odpowiedź na pytanie czy win32 jest thread-safe... właściwie to po części, bo żadnego thread-safe powszechnie rozumianego nie ma (normalnej synchronizacji), ale z założenia zrobione jest to tak, że procedurka okna (przetwarzanie komunikatów) zawsze będzie wykonywana tylko w wątku okna (pompującego komunikaty), nawet gdy SendMessage (i jego wrappery, czyli reszta funkcji GUI) zostanie wywołany w innym wątku, dba o to, aby komunikat przetworzyć w wątku okna, ważne tylko, aby nie zablokować wątku okna, bo wtedy SendMessage z innego wątku da jedynie deadlocka, dzięki którego przypadkowo poznałem ten mechanizm...

0

pozowle sobie jeszcze dodac (troche pozno), ze jest jeszcze nie czekajaca PostMessage.

Ale (dla przypomnienia) nawet jak obie nie blokuja to jesli przekazuje sie miedzy roznymi watkami wskazniki to nadal nalezy pamietac o ich synchronizacji (bo najczesciej dostep do danych globalnych).

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0