20

Jaka jest główna różnica między dwoma z następujących metod:Różnica między ThreadPool.QueueUserWorkItem a Parallel.ForEach?

ThreadPool.QueueUserWorkItem

Clients objClient = new Clients(); 
    List<Clients> objClientList = Clients.GetClientList(); 

    foreach (var list in objClientList) 
    { 
     ThreadPool.QueueUserWorkItem(new WaitCallback(SendFilesToClient), list); 
    } 

System.Threading.Tasks.Parallel ForEach

Clients objClient = new Clients(); 
    List<Clients> objClientList = Clients.GetClientList(); 

    Parallel.ForEach<Clients>(objClientList, list => 
    { 
     SendFilesToClient(list); 
    }); 

jestem nowy wielowątkowość i chcą wiedzieć, co się stanie w każdym przypadku (pod względem procesu realizacji) jaki jest poziom wątku dla każdego podejścia? Pomóż mi zwizualizować oba procesy.

SendFilesToClient: pobiera dane z bazy danych, konwertuje do programu Excel i wysyła plik Excela do danego klienta.

Dzięki!

Odpowiedz

21

Główna różnica jest funkcjonalna. Parallel.ForEach będzie blokować (według projektu), więc nie powróci, dopóki wszystkie obiekty nie zostaną przetworzone. Twoja kolejka wątków wątku w kolejce będzie przepychać pracę na wątki w tle, a nie blokować.

Wersja Parallel.ForEach ma również inne istotne zalety - nieobsłużone wyjątki zostaną z powrotem przeniesione na stronę połączenia, zamiast pozostawione bez obsługi w wątku wątku.

Ogólnie rzecz biorąc, Parallel.ForEach będzie bardziej wydajny. Obie opcje używają ThreadPool, ale Parallel.ForEach inteligentnie partycjonuje, aby zapobiec overthreading i zmniejszyć ilość narzutu wymaganego przez program planujący. Poszczególne zadania (które zostaną odwzorowane na wątki ThreadPool) zostaną ponownie użyte i skutecznie "połączone" w celu zmniejszenia obciążenia, zwłaszcza jeśli SendFilesToClient jest szybką operacją (co w tym przypadku nie będzie prawdą).

Zauważ, że można też jako trzeciej opcji, użyj PLINQ:

objClientList.AsParallel().ForAll(SendFilesToClient); 

To będzie bardzo podobna do metody Parallel.ForEach pod względem wydajności i funkcjonalności.

+0

Dzięki za szczegółowe wyjaśnienie @ Reed. Dwa pytania: 1) Dlaczego blok jest ważny (byłoby wspaniale, gdybyś mógł odpowiedzieć w odniesieniu do mojego kodu)? 2) Dalsze rozszerzenie głównego pytania, czy jest jakaś dodatkowa korzyść z używania PLINQ przez Parallel.ForEach? – Learner

+0

@ Mihir 1) blokowanie jest po prostu inne. Wątek, który właśnie uruchomisz, będzie czekał na zakończenie Parallel.ForEach przed uruchomieniem następnego wiersza kodu, ale kod foreach/TP.QUWI nie będzie czekać. 2) Brak korzyści, inny niż potencjalnie prostszy kod do zrozumienia –

+0

Wielki, dzięki za wyjaśnienie ponownie! – Learner