Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Вопрос по многопоточности


Автор: Stas123 5.7.2011, 10:04
Есть приложение WPF. В нем с помощью BackgroundWorker происходит работа.
Время от времени, эта работа в потоке BackgroundWorker генерит свои результаты, которые я хочу вывести на экран сразу, а не дожидаясь окончания работы потока. Я пытался вывести их так - добавить в ObservableCollection и вывести через ListView и DisplayMemberBinding. Но оказалось ,что нельзя обновить элементы окна не из потока диспетчера. Поэтому я сделал так.
Код

this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 

(ThreadStart) delegate()
                                        

        {Mydata.Add(data);});

все это находится в цикле и вызывается несколько раз.
Скажите, правильное ли это решение и не нужно ли тут как-то отсоединяться от потока окна диспетчера, с  учетом того, 
что данный код выполняется несколько раз до оконания работы потока BackgroundWorker ?

Автор: ДобренькийПапаша 5.7.2011, 10:10
Цитата(Stas123 @  5.7.2011,  10:04 Найти цитируемый пост)
Скажите, правильное ли это решение и не нужно ли тут как-то отсоединяться от потока окна диспетчера, с  учетом того, 
что данный код выполняется несколько раз до оконания работы потока BackgroundWorker ? 

Да я, вроде бы, ничего не отсоединял smile И так должно работать. А вот это по теме:
http://msdn.microsoft.com/ru-ru/magazine/cc163328.aspx

Автор: Brilona 5.7.2011, 10:12
Думаю, что промежуточные результаты работы BackgroundWorker'а нужно выводить в обработчике события ProgressChanged, которое возникает при вызове метода ReportProgress. http://msdn.microsoft.com/ru-ru/library/system.componentmodel.backgroundworker.aspx.

Автор: ДобренькийПапаша 5.7.2011, 10:17
Цитата(Brilona @  5.7.2011,  10:12 Найти цитируемый пост)
Думаю, что промежуточные результаты работы BackgroundWorker'а нужно выводить в обработчике события ProgressChanged, которое возникает при вызове метода ReportProgress. Тут есть пример. 

Так код, который привёл топикстартер, видимо и находится в ProgressChanged)))

Автор: Stas123 5.7.2011, 10:22
Цитата(ДобренькийПапаша @  5.7.2011,  10:17 Найти цитируемый пост)
Так код, который привёл топикстартер, видимо и находится в ProgressChanged))) 
 Нет, не находится. Вроде нормально работает. А лучше поместить в ProgressChanged ?

Автор: ДобренькийПапаша 5.7.2011, 10:26
Цитата(Stas123 @  5.7.2011,  10:22 Найти цитируемый пост)
Нет, не находится. Вроде нормально работает. А лучше поместить в ProgressChanged ? 

Было бы логично.

Автор: -Mikle- 7.7.2011, 08:42
Цитата(Stas123 @  5.7.2011,  13:22 Найти цитируемый пост)
А лучше поместить в ProgressChanged 

И не придется тогда использовать диспетчер. Событие ProgressChanged возникает в основном потоке.

Автор: Stas123 14.7.2011, 16:48
-Mikle-,  а как мне передать data, который я хочу положить в коллекцию в backgroundWorker_ProgressChanged?

Автор: Brilona 15.7.2011, 09:45
Событие ProgressChanged возникает при вызове метода http://msdn.microsoft.com/ru-ru/library/a3zbdb1t%28v=VS.95%29.aspx.

Код

worker.ReportProgress(i * 10, data);


Код

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //здесь можно получить data из e.UserState
}


Автор: Stas123 15.7.2011, 11:31
у меня почему-то не работает.
Код

if (_backgroundWorker.WorkerReportsProgress){
                    MessageBox.Show(_backgroundWorker.WorkerReportsProgress.ToString());
                    _backgroundWorker.ReportProgress(1, data);
                }
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            MyData data= (MyData ) e.UserState;
            MessageBox.Show(data.ToString());
        }

Даже так.
Код

if (_backgroundWorker.WorkerReportsProgress){
                    MessageBox.Show(_backgroundWorker.WorkerReportsProgress.ToString());
                    _backgroundWorker.ReportProgress(1);
                }

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            MessageBox.Show("Ok");
            
        }


(_backgroundWorker.WorkerReportsProgress == true

Автор: Brilona 15.7.2011, 14:26
Лучше бы написали КАК не работает. В сообщениях выводится не то, что вы ожидали? Возможно вообще какое-то из сообщений не выводится? В определенном месте появляется exception? 

P.S. Как мне кажется, сообщение в этой части
Код

if (_backgroundWorker.WorkerReportsProgress){
                    MessageBox.Show(_backgroundWorker.WorkerReportsProgress.ToString());
                    _backgroundWorker.ReportProgress(1, data);
                }

не должно отобразиться, потому как действия происходят в другом потоке.

Автор: Stas123 15.7.2011, 15:11
Код


if (_backgroundWorker.WorkerReportsProgress){
                    MessageBox.Show(_backgroundWorker.WorkerReportsProgress.ToString());
                    _backgroundWorker.ReportProgress(1, data);
                }


Здесь сообщение выводится.
Не выводится сообщение , которое должно возникать, когда происходит обработка события ProgressChanged и не происходит ничего из того, что находится в этом методе.

Автор: Brilona 15.7.2011, 15:37
Такая строка присутствует в коде?

Код

_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);

Автор: Stas123 15.7.2011, 17:26
нет.

Автор: Stas123 19.7.2011, 10:19
Brilona, ,Спасибо ,теперь все работает.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)