BackgroundWorker vs background Thread

Mam pytanie stylistyczne dotyczące wyboru implementacji wątku w tle, którego powinienem użyć w aplikacji Windows form. Obecnie mam BackgroundWorker Na postaci, która ma nieskończoną pętlę (while(true)). W tej pętli używam WaitHandle.WaitAny, aby wątek odsypiał, dopóki nie wydarzy się coś interesującego. Jednym z uchwytów zdarzeń, na które czekam, jest Zdarzenie" StopThread", dzięki któremu mogę wyjść z pętli. To zdarzenie jest sygnalizowane, gdy z mojego overridden Form.Dispose().

Czytałem gdzieś, że {[0] } jest naprawdę przeznaczony do operacje, z którymi nie chcesz wiązać interfejsu użytkownika i które mają skończony koniec - takie jak pobieranie pliku lub przetwarzanie sekwencji elementów. W tym przypadku "koniec" jest nieznany i tylko wtedy, gdy okno jest zamknięte. Czy byłoby więc bardziej odpowiednie dla mnie użycie wątku tła zamiast BackgroundWorker w tym celu?

Author: Naser Asadi, 2009-10-02

11 answers

Z mojego zrozumienia Twojego pytania, używasz BackgroundWorker jako standardowego wątku.

Powodem, dla którego BackgroundWorker jest zalecane dla rzeczy, które nie chcą związać wątku interfejsu, jest to, że eksponuje kilka fajnych wydarzeń podczas tworzenia formularzy Win.

Zdarzenia takie jak RunWorkerCompleted sygnalizują, że wątek zakończył pracę, a Zdarzenie ProgressChanged aktualizuje GUI w wątkach.

Więc jeśli nie używasz ich, nie widzę żadnych szkoda w używaniu standardowego wątku do tego, co musisz zrobić.

 76
Author: ParmesanCodice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-04 08:55:11

Niektóre z moich myśli...

  1. Użyj BackgroundWorker , Jeśli masz pojedyncze zadanie, które działa w tle i wymaga interakcji z interfejsem użytkownika. Zadanie gromadzenia danych i wywołań metod do wątku interfejsu użytkownika jest obsługiwane automatycznie za pomocą modelu opartego na zdarzeniach. Unikaj BackgroundWorker jeśli...
    • twój zespół nie ma lub nie oddziałuje bezpośrednio z interfejsem użytkownika,
    • musisz wątek być pierwszoplanowym wątkiem, lub
    • musisz manipulować priorytet wątku.
  2. Użyj wątku , gdy wymagana jest wydajność. ThreadPool pomaga uniknąć napowietrznych związanych z tworzeniem, uruchamianiem i zatrzymywaniem wątków. Unikaj używania ThreadPool if...
    • zadanie działa przez cały okres użytkowania aplikacji,
    • aby wątek był pierwszoplanowym wątkiem,
    • musisz manipulować priorytetem wątku, lub
    • musisz wątek mieć stałą tożsamość (przerywanie, zawieszanie, odkrywanie).
  3. Użyj klasy Thread do długotrwałych zadań i gdy potrzebujesz funkcji oferowanych przez formalny model wątku, np. wybieranie między wątkami pierwszoplanowymi i tła, poprawianie priorytetu wątku, drobnoziarnista kontrola nad wykonaniem wątku itp.
 341
Author: Matt Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-22 13:12:11

Prawie to, co powiedział Matt Davis, z następującymi dodatkowymi punktami:

Dla mnie głównym różniczkownikiem z BackgroundWorker jest automatyczne ustawianie zakończonego zdarzenia za pomocą SynchronizationContext. W kontekście interfejsu oznacza to, że ukończone zdarzenie zostanie wywołane w wątku interfejsu i może być użyte do aktualizacji interfejsu. Jest to główny wyróżnik, jeśli używasz BackgroundWorker w kontekście interfejsu użytkownika.

Zadania wykonywane przez ThreadPool nie mogą być łatwo anulowane (dotyczy to również ThreadPool. QueueUserWorkItem i delegaci wykonują asynchronicznie). Jeśli chcesz anulować, użyj BackgroundWorker lub (bardziej prawdopodobne poza interfejsem) spin up wątku i zachowaj odniesienie do niego, aby móc wywołać Abort().

 11
Author: piers7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 17:16:27

Również wiązasz wątek na całe życie pracownika tła, co może być niepokojące, ponieważ jest ich tylko skończona liczba. Powiedziałbym, że jeśli tworzysz wątek tylko raz dla swojej aplikacji (i nie używasz żadnej z funkcji workera w tle), użyj wątku, a nie wątku backgroundworker/threadpool.

 10
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-02 00:08:35

Wiesz, czasami łatwiej jest pracować z Backgroundworkerem, niezależnie od tego, czy używasz Windows Forms, WPF czy jakiejkolwiek technologii. Fajną częścią tych facetów jest to, że dostajesz wątek bez martwienia się zbytnio o to, gdzie wykonujesz wątek, co jest Świetne do prostych zadań.

Przed użyciem BackgroundWorker najpierw zastanów się, czy chcesz anulować wątek (zamknięcie aplikacji, anulowanie użytkownika), a następnie zdecyduj, czy wątek powinien sprawdzić anulowanie, czy powinno być wymuszone na samej egzekucji.

BackgroundWorker.CancelAsync() ustawia CancellationPending na true, ale nie zrobi nic więcej, to wtedy wątki są odpowiedzialne za ciągłe sprawdzanie tego, pamiętaj również, że możesz skończyć z stanem wyścigu w tym podejściu, w którym Użytkownik anulował, ale wątek zakończył się przed testowaniem dla CancellationPending.

Thread.Abort() z drugiej strony rzuci wyjątek w ramach wykonywania wątku, który wymusza anulowanie tego wątku, należy uważać na to, co może być niebezpieczne, jeśli ten wyjątek zostanie nagle podniesiony w trakcie egzekucji.

Gwintowanie wymaga bardzo starannego rozważenia bez względu na to, jakie zadanie, dla niektórych dalszych czytań:

Programowanie równoległe w. NET Framework Najlepsze Praktyki Managed Threading

 8
Author: Brett Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 10:27:59

Wiedziałem, jak używać wątków, zanim poznałem. NET, więc trochę się przyzwyczaiłem, gdy zacząłem używać BackgroundWorkers. Matt Davis podsumował tę różnicę z wielką doskonałością, ale dodam, że trudniej jest dokładnie zrozumieć, co robi kod, a to może utrudnić debugowanie. Łatwiej jest myśleć o tworzeniu i zamykaniu wątków, IMO, niż myśleć o oddaniu pracy do puli wątków.

Nadal nie mogę komentować postów innych osób, więc wybacz moją chwilową kulawość w użyciu odpowiedzi na adres piers7

Nie używaj wątku.Abort (); zamiast tego zasygnalizuj Zdarzenie i zaprojektuj swój wątek tak, aby zakończył się z wdziękiem po sygnalizacji. Nić.Abort() powoduje wywołanie ThreadAbortException w dowolnym momencie wykonywania wątku, które może robić różnego rodzaju nieszczęśliwe rzeczy, takie jak osierocone Monitory, uszkodzony stan współdzielony i tak dalej. http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

 4
Author: ajs410,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-28 20:31:29

Jeśli nie jest zepsuty-napraw go, aż będzie...tylko żartowałem:)

Ale poważnie BackgroundWorker jest prawdopodobnie bardzo podobny do tego, co już masz, gdybyś zaczął z nim od początku, może zaoszczędziłbyś trochę czasu - ale w tym momencie nie widzę potrzeby. Chyba, że coś nie działa, albo uważasz, że twój obecny kod jest trudny do zrozumienia, wtedy trzymałbym się tego, co masz.

 2
Author: Gandalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-01 22:34:08

Podstawową różnicą jest, tak jak powiedziałeś, generowanie zdarzeń GUI z BackgroundWorker. Jeśli wątek nie musi aktualizować wyświetlacza ani generować zdarzeń dla głównego wątku GUI, może to być prosty wątek.

 2
Author: David R Tribble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-01 23:09:51

Worker w tle to klasa, która działa w osobnym wątku, ale zapewnia dodatkową funkcjonalność, której nie można uzyskać w prostym wątku (np. obsługa raportu postępu zadań).

Jeśli nie potrzebujesz dodatkowych funkcji podanych przez pracownika w tle - a wydaje się, że nie - wtedy wątek byłby bardziej odpowiedni.

 1
Author: Cesar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-01 22:34:57

Chcę zwrócić uwagę na jedno zachowanie klasy BackgroundWorker, o którym jeszcze nie wspomniano. Możesz utworzyć normalny wątek do uruchomienia w tle, ustawiając wątek.IsBackground property.

Wątki tła są identyczne z wątkami pierwszoplanowymi, z tym wyjątkiem, że wątki tła nie uniemożliwiają zakończenia procesu. [1]

Możesz przetestować to zachowanie, wywołując następującą metodę w konstruktorze okna formularza.

void TestBackgroundThread()
{
    var thread = new Thread((ThreadStart)delegate()
    {
        long count = 0;
        while (true)
        {
            count++;
            Debug.WriteLine("Thread loop count: " + count);
        }
    });

    // Choose one option:
    thread.IsBackground = false; // <--- This will make the thread run in background
    thread.IsBackground = true; // <--- This will delay program termination

    thread.Start();
}

Kiedy Właściwość IsBackground jest ustawiona na true i zamykasz okno, wtedy Twoja aplikacja zakończy się normalnie.

Ale gdy właściwość IsBackground jest ustawiona na false (domyślnie) i zamkniesz okno, wtedy tylko okno zniknie, ale proces nadal będzie działał.

Klasa BackgroundWorker wykorzystuje wątek, który działa w tle.

 1
Author: Doomjunky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-11 14:05:34

To, co mnie zastanawia, to fakt, że visual studio designer pozwala tylko na korzystanie z Backgroundworkerów i timerów, które tak naprawdę nie współpracują z projektem usługi.

To daje schludne przeciągnij i upuść kontrolki do usługi, ale... nawet nie próbuj go instalować. To nie zadziała.

Usługi: Używaj tylko systemu.Zegary.Timer System.Okna.Formularze.Timer nie będzie działać, nawet jeśli jest dostępny w toolbox

Usługi: BackgroundWorkers nie będzie działać, gdy działa jako serwis Użyj Systemu.Gwintowanie.ThreadPools zamiast lub asynchroniczne wywołania

 0
Author: scottweeden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-17 03:29:31