Mam scenariusz (Windows Forms, C #, .NET)
- Istnieje główna forma, która obsługuje kontrolę użytkowników.
- Kontrola użytkownika wykonuje pewne ciężkie operacje na danych, tak że jeśli bezpośrednio wywołam
UserControl_Load
metodę, interfejs użytkownika przestanie odpowiadać na czas wykonywania metody ładowania. - Aby temu zaradzić, ładuję dane do innego wątku (próbując jak najmniej zmienić istniejący kod)
- Użyłem wątku procesu roboczego w tle, który będzie ładował dane, a po zakończeniu powiadomi aplikację, że wykonała swoją pracę.
- Teraz przyszedł prawdziwy problem. Cały interfejs użytkownika (formularz główny i jego potomne kontrolki użytkownika) został utworzony w głównym wątku głównym. W metodzie LOAD kontrolera użytkownika pobieram dane na podstawie wartości niektórych formantów (takich jak pole tekstowe) na userControl.
Pseudokod wyglądałby tak:
KOD 1
UserContrl1_LoadDataMethod()
{
if (textbox1.text == "MyName") // This gives exception
{
//Load data corresponding to "MyName".
//Populate a globale variable List<string> which will be binded to grid at some later stage.
}
}
Wyjątkiem było
Nieprawidłowa operacja krzyżowa: dostęp uzyskany z wątku innego niż wątek, w którym został utworzony.
Aby dowiedzieć się więcej na ten temat, zrobiłem trochę googlowania i pojawiła się sugestia, jak użycie następującego kodu
KOD 2
UserContrl1_LoadDataMethod()
{
if (InvokeRequired) // Line #1
{
this.Invoke(new MethodInvoker(UserContrl1_LoadDataMethod));
return;
}
if (textbox1.text == "MyName") // Now it wont give an exception
{
//Load data correspondin to "MyName"
//Populate a globale variable List<string> which will be binded to grid at some later stage
}
}
ALE ALE ALE ... wygląda na to, że wróciłem do pierwszego. Aplikacja ponownie przestaje odpowiadać. Wydaje się, że jest to spowodowane wykonaniem linii nr 1, jeśli warunek. Zadanie ładowania jest ponownie wykonywane przez wątek nadrzędny, a nie trzeci odrodzony.
Nie wiem, czy postrzegałem to dobrze, czy źle. Jestem nowy w wątkach.
Jak to rozwiązać, a także jaki jest efekt wykonania linii nr 1, jeśli blok?
Sytuacja jest następująca : chcę załadować dane do zmiennej globalnej na podstawie wartości kontrolki. Nie chcę zmieniać wartości kontrolki z wątku potomnego. Nie zrobię tego nigdy z dziecięcego wątku.
Tak więc dostęp tylko do wartości, aby odpowiednie dane mogły zostać pobrane z bazy danych.