2010-06-04 9 views
7

Mam aplikację konsolową, którą przesyłam do WPF. Aplikacja ma 3 wątki robocze, wszystkie są połączone z głównym wątkiem, zanim niektóre wyniki wyjściowe zostaną wydrukowane na ekranie. Rozumiem, że jeśli spróbuję zrobić to samo w aplikacji WPF, GUI zostanie zablokowany i nie będzie responsywny dla użytkownika. Jak mogę powiadomić wątek nadrzędny, że wszystkie wątki zakończyły swoją pracę? Myślę, że rozwiązanie będzie wymagało delegatów i zdarzeń (a może i BackgroundWorker?), Ale nie było dla mnie jasne, jak wywołać wywołanie zwrotne po zakończeniu wątku.Jak powiadomić wątek nadrzędny, że wszystkie wątki potomne zostały zakończone?

Original Kod:

foreach (Thread t in threadList) 
{ 
       t.Start(); 
} 

foreach (Thread t in threadList) 
{ 
       t.Join(); 
} 

// print some results here 

Odpowiedz

6

Jeśli używasz trzy BackgroundWorker s, można użyć zdarzenia RunWorkerCompleted zauważyć, że jeden z pracowników jest zakończona: Przed rozpoczęciem robotnikom ustawić licznik do 3 następnie zmniejszyć i sprawdzić ten licznik w metodzie zwanej przez RunWorkerCompleted jeżeli trafia 0, jesteś skończony.

1

Spójrz na tego article w MSDN Magazine, który daje na przykład za pomocą BackgroundWorker. Zacznij od rysunku 7.

3

Powinieneś użyć trzech BackgroundWorkers.

Następnie można obsługiwać ich zdarzenia RunWorkerCompleted, aby dowiedzieć się, kiedy zakończą się operacje.

0

Jeśli chcesz tylko do sondowania wątków roboczych, można użyć coś takiego bool threadWasDone = thread.Join(0);

1

zależy od tego co chcesz osiągnąć. Jaką formę komunikacji próbujesz ułatwić?

Jeśli miałbym zgadywać, to, czego naprawdę chcesz, to po prostu zgłosić [lub wyświetlić] wyniki twojego pracownika w twojej aplikacji. Jeśli jest to przypadek, to w typowej aplikacji WPF masz widok modelu, powiedzmy

public class AwesomeViewModel : INotifyPropertyChanged 
{ 
    // if small fixed number, otherwise, you could use 
    // an ObservableCollection<T> 
    public string WorkerResultA { ... } 
    public string WorkerResultB { ... } 
    public string WorkerResultC { ... } 
} 

które jest powiązane z danymi do kontroli WPF. Możesz po prostu przekazać odwołanie do modelu widoku do każdego wątku roboczego i zaktualizować klasę bez konieczności blokowania \ oczekujących na wątek Gui. W ten sposób każdy pracownik zgłasza swoje wyniki, gdy kończy się bez interwencji innej osoby. Jest to optymalne.

Oczywiście, jeśli wykonasz to samo, you run into another completely different issue. Które, fyi, można rozwiązać za pomocą Dispatchera. One possible solution here.

Jeśli chodzi o BackgroundWorker kontra wyraźna kontrola Thread, to zależy od Ciebie. Są obie zalety, ale pamiętaj, że masz już napisany kod funkcjonalny. To, i według mojej osobistej opinii, BackgroundWorker nie jest szczególnie użyteczne.

Jeśli naprawdę absolutnie pozytywnie musi wdrożyć bardziej wyrafinowanego modelu synchronizacji, to bardzo polecam odświeżyć ManualResetEvent swojego kuzyna AutoResetEvent, Semaphore, kluczowego lock i jednoczesnego programowania w ogóle. Niestety, nie ma tam skrótów :)

Mam nadzieję, że to pomoże!

Powiązane problemy