Как обновить метку из потока BackgroundWorker?

Когда я использовал WinForms, я бы сделал это в своем методе bg_DoWork:

status.Invoke(new Action(() => { status.Content = e.ToString(); }));
status.Invoke(new Action(() => { status.Refresh(); }));

Однако в моем приложении WPF я получаю сообщение об ошибке, говорящее, что Invoke не существует для Label.

Любая помощь будет оценена по достоинству.


person software is fun    schedule 22.05.2015    source источник


Ответы (5)


Это поможет вам.

Выполнить синхронно:

Application.Current.Dispatcher.Invoke(new Action(() => { status.Content = e.ToString(); }))

Для асинхронного выполнения:

Application.Current.Dispatcher.BeginInvoke(new Action(() => { status.Content = e.ToString(); }))
person Gopichandar    schedule 22.05.2015

Используйте возможности, уже встроенные в BackgroundWorker. Когда вы «отправляете отчет о прогрессе», он отправляет ваши данные в событие ProgressChanged, которое выполняется в потоке пользовательского интерфейса. Нет необходимости звонить Invoke().

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    bgWorker.ReportProgress(0, "Some message to display.");
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    status.Content = e.UserState.ToString();
}

Убедитесь, что вы установили bgWorker.WorkerReportsProgress = true, чтобы включить отчеты о ходе выполнения.

person Grant Winney    schedule 22.05.2015
comment
Этот. Потому что вы действительно не хотите обновлять элементы управления пользовательского интерфейса в разных потоках. - person Mike Eason; 22.05.2015

Если вы используете WPF, я бы посоветовал изучить DataBinding.

«Способ WPF» для подхода к этому заключается в том, чтобы привязать свойство метки Content к некоторому свойству вашей модели. Таким образом, обновление модели автоматически обновляет метку, и вам не нужно беспокоиться о самостоятельной сортировке потоков.

Есть много статей о WPF и привязке данных, это, вероятно, хорошее место для начала: http://www.wpf-tutorial.com/data-binding/hello-bound-world/

person paul    schedule 22.05.2015

Вам нужно использовать

Dispatcher.Invoke(new Action(() => { status.Content = e.ToString(); }))

вместо status.Invoke(...)

person Jens    schedule 22.05.2015

Вам действительно следует подумать об использовании возможностей «привязки данных» в WPF.

Вы должны обновить объект в своей модели представления и привязать его к элементу управления пользовательского интерфейса.

См. MVVM Light. Легко и просто использовать. Не кодируйте WPF без него.

person AndrewJE    schedule 22.05.2015
comment
Вам не нужна какая-либо причудливая структура для использования шаблона проектирования MVVM. Хотя это делает некоторые вещи немного проще в управлении. - person Mike Eason; 22.05.2015