środa, 13 lutego 2013

[C#|Visual Studio] Threading: BackgroundWorker

Aplikacje pisane w takich technologiach jak WinForms czy WPF wymagają, aby interfejs użytkownika był responsywny niemal przez cały czas. Zatem wszystkie kosztowne czasowo operacje powinny być wykonywane asynchronicznie. Klasą, która umożliwia łatwe przeprowadzanie takich operacji jest BackgroundWorker. Klasa ta dostarcza kilka gotowych mechanizmów, takich jak:
  • łatwa możliwość przerwania pracy
  • możliwość bezpiecznej aktualizacji kontrolek WPF i Formsowych
  • przekazywanie wyjątków do wątku nadrzędnego
  • możliwość raportowania o stanie pracy workera
Poniższy przykład obrazuje wszystkie możliwości BackgroundWorkera:

static BackgroundWorker _bw;

public static void Run()
{
    _bw = new BackgroundWorker
    {
        WorkerReportsProgress = true,
        WorkerSupportsCancellation = true
    };
    _bw.DoWork += bw_DoWork;
    _bw.ProgressChanged += bw_ProgressChanged;
    _bw.RunWorkerCompleted += bw_RunWorkerCompleted;
    _bw.RunWorkerAsync ("Hello to worker");
    Console.WriteLine ("Press Enter in the next 5 seconds to cancel");
    Console.ReadLine();
    if (_bw.IsBusy) _bw.CancelAsync();
    Console.ReadLine();
}

static void bw_DoWork (object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 100; i += 20)
    {
        if (_bw.CancellationPending) { e.Cancel = true; return; }
        _bw.ReportProgress (i);
        Thread.Sleep (1000);
    }
    e.Result = 123;
}

static void bw_RunWorkerCompleted (object sender,
                                    RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
        Console.WriteLine ("You canceled!");
    else if (e.Error != null)
        Console.WriteLine ("Worker exception: " + e.Error.ToString());
    else
        Console.WriteLine ("Complete: " + e.Result);      // from DoWork
}

static void bw_ProgressChanged (object sender,
                                ProgressChangedEventArgs e)
{
    Console.WriteLine ("Reached " + e.ProgressPercentage + "%");
}

Ustawienie odpowiednich propercji i zapięcie callbacków na zdarzenia jest konieczne w przypadku, gdy chcemy mieć możliwość anulowania i raportowania stanu pracy workera. Obie możliwości są opcjonalne. Dane pomiędzy wątkami przekazywane są poprzez odpowiednie EventArgs.

Brak komentarzy:

Prześlij komentarz