Использование BackgroundWorker
не освобождает вас от обычных правил потоковой передачи, таких как only , поток UI может обращаться к компонентам пользовательского интерфейса.
Если вы хотите обновить UI из BackgroundWorker
, кроме , используя события прогресса / завершения (которые возникают в потоке пользовательского интерфейса), вам нужно использовать Control.Invoke
/ Control.BeginInvoke
так же, как и в других ситуациях. Например:
if (....)
{
Action action = () => richtextBox.Text.Add("MyText");
richtextBox.Invoke(action); // Or use BeginInvoke
}
попробуйте этот код,
BeginInvoke((MethodInvoker)delegate
{
richtextBox.Text.Add("MyText");
});
Чтобы сделать его более чистым и основанным на предположении Джона Скита, я сделал метод расширения, который делает то же самое, вы можете изменить «this Label control
» на this TextBox control
или просто использовать «this Control control
» (и в основном разрешать каждый управление легко обновляется):
internal static class ExtensionMethods
{
/// <summary>
/// Updates the label text while being used in a multithread app.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="text">The text.</param>
internal static void UpdateThreadedText(this Label control, string text)
{
Action action = () => control.Text = text;
control.Invoke(action);
}
/// <summary>
/// Refreshes the threaded.
/// </summary>
/// <param name="control">The control.</param>
internal static void RefreshThreaded(this Label control)
{
Action action = control.Refresh;
control.Invoke(action);
}
}
И тогда использование довольно просто:
this.yourLabelName.UpdateThreadedText("This is the text");
this.yourTextBoxName.UpdateThreadedText("This is the text");
this.yourControlName.UpdateThreadedText("This is the text");
или
this.yourLabelName.RefreshThreaded();
Работает для меня красиво :)
Я думаю, что ошибка останавливается в этой строке:
richtextBox.Text.Add("MyText");
ваш вопрос i похож на этот:
BackgroundWorker OnWorkCompleted выбрасывает исключение поперечной нити
Добавить:
e.Result = "MyText";
В вашем bw_DoWork
И:
richTextBox1.AppendText((string)e.Result);
В вашем bw_RunWorkerCompleted
(измените его, чтобы он соответствовал вашим код)
EDIT:
Если это было сделано много раз во время работы BackgroundWorker
, вы можете добавить:
_bw.ReportProgress(0, "MyText");
в bw_DoWork
и:
richTextBox1.AppendText((string)e.UserState);
в bw_ProgressChanged
.
Вы также можете попробовать это.
this.Invoke(new MethodInvoker(delegate()
{
richtextBox.Text.Add("MyText");
}));
Используя компонент BackgroundWorker, только события ProgressChanged
и RunWorkerCompleted
позволяют вам вызывать методы / свойства элементов управления пользовательского интерфейса (которые всегда должны выполняться в потоке пользовательского интерфейса). При обновлении пользовательского интерфейса в событии DoWork
, которое выполняется в потоке, отличном от UI, вы получаете эту ошибку, возможно, вам нужно обновить элементы управления пользовательским интерфейсом с помощью методов Invoke или BeginInvoke в DoWork, если вы хотите.