backgroundWorker a thread oraz Dispatcher w WPF

0

Witam ponownie :)
Czytam sobie o aplikacjach wielowątkowych i mam kilka pytań.

Czy ktoś może mi w miarę przystępnie wyjaśnij różnice między tworzeniem wątków przy pomocy backgroundWorker a thread.
Mam kod:

var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(Wykonaj_DoWork);

Oraz

var backgroundThread = new Thread(new ThreadStart(Wykonaj));
backgroundThread.Start();

Oba przykłady tworzą nowy wątek, w którym mogę wykonywać różne operacje – zgadza się?
Są jakieś zalecenia, kiedy należy zastosować dane rozwiązanie? Czy mogę je stosować zamiennie?

…i jeszcze mam pytanie dotyczące WPF i operowania na kontrolkach w nowych wątku. Po problemach z wyświetleniem tekstu w TextBlock w nowym wątku, znalazłam rozwiązanie z wykorzystaniem Dispatcher, np.:

private void Wykonaj_DoWork(object sender, DoWorkEventArgs e)
{
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
        (ThreadStart)delegate()
        {
            TextBlockMsg1.Text = “komunikat z nowego wątku”
        }
}

Moje pytanie dotyczy tego co właściwie dzieje się wewnątrz tego Dispatcher? Czy operacja przypisania tekstu do TextBlockMsg1 odbywa się w drugim wątku, czy jednak w pierwszym wątku? Bo mam wrażenie, że w pierwszym. Wszystko przez kod:

private void ButtonTest_Click(object sender, RoutedEventArgs e)
{
    var backgroundWorker = new BackgroundWorker();
    backgroundWorker.DoWork += new DoWorkEventHandler(Wykonaj_DoWork);

    var pierwszy = Thread.CurrentThread;
    pierwszy.Name = "Pierwszy wątek";
    TextBlockMsg1.Text = pierwszy.Name;
}

private void Wykonaj_DoWork(object sender, DoWorkEventArgs e)
{
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
        (ThreadStart)delegate()
        {
          var drugi = Thread.CurrentThread;
          TextBlockMsg2.Text = drugi.Name;
        }
}

W Wykonaj_DoWork wyświetlam nazwę dla drugiego wątku (a przynajmniej tak myślałam)… i dostaję nazwę, którą przypisałam w pierwszym wątku.
Jeżeli przesunę var drugi = Thread.CurrentThread przed this.Dispatcher.BeginInvoke to już mam nazwę drugiego wątku.
Czyli, że to co jest poza Dispatcher wykonuję w drugim wątku, a kod wewnątrz znowu w pierwszym - tak?

Zuza

1

http://stackoverflow.com/questions/4757159/difference-between-backgroundworker-and-thread

Jak robisz invoke, to okreslasz instrukcje ktore wykonywane sa przez watek odpowiedzialny za GUI

1

W pierwszych wydaniach .net wprowadzono asynchroniczność w klasie Thread. Na podstawie Thread zaimplementowano backgroundWorkera czyli taką niby kontolkę, którą możesz przeciągnąć na edytorze GUI. Oczywiście jest on opakowany w klasy więc można go używać z code behind. Natomiast od wersji chyba 4.0 .neta wprowadzono Taski. Są one nadbudówką klas Thread jednak taski zawsze odpalane są w ramach puli. Dodatkowo taski i słowa kluczowe async/await w bardzo prosty i przyjemny sposób załatwiają synchronizację między wątkami jak i kontrolkami. backgroun worker też ma to zaimplementowane ale w inny sposób, za pomocą eventów np. WorkCompleted i ReportProgress itd.

Dispatcher.BeginInvoke i Dispatcher.Invoke kontrolek WPF to odpowiednio pula metod do wykonania asynchronicznie/synchronicznie przez główny wątek GUI. Co jakiś czas główny wątek obsługuje listę przekazanych metod na rzecz danej kontrolki. Można wyłączyć sprawdzanie przez kontrolkę czy żądanie wykonania pochodzi z wątku który aktywował kontrolkę
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls.aspx .

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