2010-06-04 3 views
7

У меня есть консольное приложение, которое я переношу в WPF. Приложение имеет 3 рабочих потока, которые все соединены с основным потоком, пока некоторые результаты вывода не будут напечатаны на экране. Я понимаю, что если я попытаюсь сделать то же самое в приложении WPF, графический интерфейс будет заблокирован и не будет отвечать за пользователя. Как тогда я могу уведомить родительский поток о том, что все потоки завершили свою работу? Я думаю, что решение будет включать в себя делегатов и событий (или, возможно, BackgroundWorker?), Но мне было непонятно, как вызвать обратный вызов, когда поток завершен.Как вы уведомляете родительский поток о завершении всех дочерних потоков?

Оригинальный код:

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

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

// print some results here 

ответ

6

Если вы используете три BackgroundWorker с, вы можете использовать это событие RunWorkerCompleted заметить, что один из рабочих завершено: Перед началом рабочих установить счетчик на 3, то уменьшают и проверить этот счетчик в методе наречено RunWorkerCompleted, если он достигает 0, вы закончили.

1

Взгляните на эту article в журнале MSDN, что дает вам пример по использованию BackgroundWorker. Начните с рисунка 7.

3

Вы должны использовать три BackgroundWorkers.

Затем вы можете обработать свои события RunWorkerCompleted, чтобы узнать, когда закончите работу.

0

Если вы просто хотите, чтобы опрашивать рабочие потоки, вы могли бы использовать что-то вроде bool threadWasDone = thread.Join(0);

1

зависит от того, что вы хотели бы достичь. Какую форму общения вы пытаетесь облегчить?

Если бы я мог предположить, что вы действительно хотите, просто сообщите [или покажите] результаты вашего работника в вашем приложении. Если это так, то в типичном приложении WPF у вас есть модель представления, скажем,

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

который данные с привязкой к элементам управления WPF. Вы можете просто передать ссылку своей модели взгляда на каждый рабочий поток, и они обновляют класс, не требуя блокировки \ ожидания в потоке Gui. Таким образом, каждый работник сообщает о своих результатах, когда он завершается без вмешательства кого-либо другого. Это оптимально.

Конечно, если вы сделаете именно это, you run into another completely different issue. Который, fyi, разрешен через Диспетчер. One possible solution here.

Что касается BackgroundWorker по сравнению с явным Thread контролем, это зависит от вас. У обоих есть преимущества, но помните, что у вас уже есть функциональный код. Это, по моему личному мнению, BackgroundWorker не особенно полезно.

Если вы действительно абсолютно положительно должны реализовать более сложную модель синхронизации, то я настоятельно рекомендую вам освежить ManualResetEvent его кузен AutoResetEvent, Semaphore, ключевое слово lock и параллельного программирования в целом. Извините, никаких ярлыков нет :)

Надеюсь, это поможет!

Смежные вопросы