Już nie po raz pierwszy przyszło mi stanąć przed utrudnieniami jakie niesie ze sobą programowanie z wykorzystaniem wątków w tle. Problem mój polega na tym, że tworzę obiekt typu BackgroundWorker o nazwie bgProcess. Mam również dwie funkcje, jedna sprawdza poprawność danych w tle, druga natomiast przesyła je do bazy danych - również w tle. Zarówno jedna jak i druga funkcja odpalana jest za pomocą swojego przycisku [Zarejestruj] oraz [sprawdź]. Teraz zaczynają się schody. Z rozwiązania, które znalazłem w internecie musiałem użyć konstrukcji:
bgProcess.DoWork += delegate(object sender, DoWorkEventArg e) { funkcja... };
Zrobiłem więc takie wywołanie zarówno w przypadku wysłania danych jak i ich sprawdzenia tzn. z grubsza coś takiego:
private void zarejestruj_Click(object sender, RoutedEventArgs e) {
bgProcess.DoWork += delegate(object s, DoWorkEventArg arg) { funkcja... };
bgProcess.ProgressChanged += delegate(object s, ProgressChangedEventArg arg) { funkcja... };
bgProcess.RunWorkedCompleted += delegate(object s, RunWorkedCompletedEventArg arg) { funckja... };
if (!bgProcess.IsBusy)
bgProcess.RunWorkerAsync(dane);
}
Niestety dzieje się coś dziwnego. Np. uruchamiam wysyłanie danych, wyskakuje komunikat informujący, że dane zostały przesłane bądź nie (który jest właściwy tylko tej funkcji), w RunWorkerCompleted odblokowuję przyciski więc wiem, że funkcja w tle skończyła się wykonywać. Odpalam więc sprawdzanie a tu niespodzianka, komunikat o stanie przesyłania danych z funkcji zarejestruj, zupełnie jakby funkcje DoWork dodały się do siebie. Podobnie z ProgressChanged - ponieważ zarejestruj przesyła do niej dane typu string a sprawdzanie typu boolean to powstaje galimatias przy ich konwertowaniu i odczytaniu jakby stało się zupełnie to samo co z DoWork. Spróbowałem więc inaczej:
private void sprawdz_Click(object sender, RoutedEventArgs e)
{
zarejestruj.IsEnabled = false;
sprawdz.IsEnabled = false;
Object[] dane = new Object[5];
dane[0] = login.Text;
dane[1] = password.Password;
dane[2] = repassword.Password;
dane[3] = email.Text;
dane[4] = reemail.Text;
bgProcess.DoWork -= registerUser_DoWork;
bgProcess.ProgressChanged -= registerUser_ProgressChanged;
bgProcess.DoWork += checkForm_DoWork;
bgProcess.ProgressChanged += checkForm_ProgressChanged;
bgProcess.RunWorkerCompleted += backgroundComplete;
if (!bgProcess.IsBusy)
bgProcess.RunWorkerAsync(dane);
}
private void zarejestruj_Click(object sender, RoutedEventArgs e)
{
zarejestruj.IsEnabled = false;
sprawdz.IsEnabled = false;
Object[] dane = new Object[5];
dane[0] = login.Text;
dane[1] = password.Password;
dane[2] = repassword.Password;
dane[3] = email.Text;
dane[4] = reemail.Text;
bgProcess.DoWork -= checkForm_DoWork;
bgProcess.ProgressChanged -= checkForm_ProgressChanged;
bgProcess.DoWork += registerUser_DoWork;
bgProcess.ProgressChanged += registerUser_ProgressChanged;
bgProcess.RunWorkerCompleted += backgroundComplete;
if (!bgProcess.IsBusy)
bgProcess.RunWorkerAsync(dane);
}
Zdefiniowałem funkcje osobno i potem próbowałem w metodzie sprawdzania wyrejestrować metody wysyłania danych, a w metodzie wysyłania danych, te funkcje które zostały zdefiniowane w rejestrującej. Niestety nie działa to w zamierzony przeze mnie sposób. backgroundComplete() odblokowuje kontrolki zarejestruj i sprawdz, nie ma więc problemu z wielowątkowością. Jak zarobić bym mógł swobodnie odpalać sobie na zmianę w tle obie te funkcje?