Monday, 3 April 2006

Dostęp do formatki z zewnętrznego wątku

W dokumentacji .Net napisane jest jednoznacznie - jedynym wątkiem, który może wykonywać jakiekolwiek operacje na formatce (System.Windows.Forms.Form) jest ten, który ją utworzył. Pozostałym wolno jedynie wywoływać metody z serii Invoke(), które z kolei zaowocują wykonaniem podanego do nich delegate w wątku formatki. A jak tego po ludzku użyć? Ano tak:


w klasie formatki

//sygnatura funkcji do wywołania z zewnątrz
delegate void SetTextDelegate(string text);
//i sama funkcja
void SetText(string text)
{
if(!InvokeRequired)//czyli wywołanie z wątku formatki
button1.Text = text;
else
Invoke(new SetTextDelegate(SetText), text);//trzeba zmienić wątek
}

natomiast użycie tego w wątku zewnętrznym to po prostu

form1.SetText((i*i).ToString());

Wersja 2.0 platformy umożliwia wykonanie tej samej operacji jeszcze prościej, mianowicie poprzez wywołanie

form1.Invoke((MethodInvoker)delegate { form1.button1.Text = (i * i).ToString(); });

Tutaj niepotrzebne są żadne dodatkowe metody w formatce, po prostu informujemy framework, że ten kawałek kodu ma być wykonany w wątku będącym właścicielem form1. Jedynym haczykiem jest rzutowanie do MethodInvoker. Jest ono konieczne, ponieważ metoda Invoke() jako parametr przyjmuje dowolny System.Delegate... który niestety sam nie jest typu delegate. Bez MethodInvoker metoda anonimowa byłaby rzutowana do System.Delegate, co skończyłoby się błędem kompilacji. A w ten sposób kompilator rozumie o co nam chodzi.

Jeśli już wykorzystywałeś wątki razem z Windows.Forms to pewnie zastanawiasz się, po co ta cała szopka, przecież można odwoływać się do formatki z innego wątku i wszystko działa? Ano działa, ale tylko na Windows XP. W tej wersji platformy .Net wprowadzono niestety zabezpiecznia przed najczęstszymi błędami związanymi z programowaniem wielowątkowym, co prowadzi do tego, iż da się na niej uruchomić kod niepoprawny, który nie zadziała np. na Windows 98 lub mono. Zresztą, w aktualnej (1.1.13.*) implementacji Windows.Forms pod tym ostatnim jest parę innych problemów - np. tworzenie formatek (całkowicie niezależnych!) w kilku różnych wątkach prowadzi do niedeterministycznego zachowania programu i częstych padów...

No comments:

Post a Comment