我有一段时间有问题
这一行:
txtPastes.Text = (string)e.UserState;
抛出一个跨线程异常,我没有找到任何解决方案
txtPastes
- 文本框
GuiUpdate
- BackgroundWorker
lstAllPastes
- 字符串列表
private void GuiUpdate_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
while (lstAllPastes.Count == 0) ;
for (int i = 0; i < lstAllPastes[0].Length; i++)
{
GuiUpdate.ReportProgress(0, lstAllPastes[0].Substring(0, i));
Thread.Sleep(1);
}
lstAllPastes.RemoveAt(0);
}
}
private void GuiUpdate_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
txtPastes.Text = (string)e.UserState;
}
private void GuiUpdate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
答案 0 :(得分:5)
您无法从UI线程以外的任何线程更新UI控件。通常,BackgroundWorker
会在UI线程上正确地提升其ProgressChanged
和RunWorkerCompleted
事件。由于此处似乎并非如此,您可以使用Invoke
方法自行将UI更新逻辑封送到UI线程:
txtPastes.Invoke(new Action(() =>
{
// This code is executed on the UI thread.
txtPastes.Text = (string)e.UserState;
}));
如果您使用WPF,则需要在控件的调度程序上调用Invoke
:
txtPastes.Dispatcher.Invoke(new Action(() =>
{
txtPastes.Text = (string)e.UserState;
}));
更新:正如Thomas Levesque和Hans Passant所提到的,您应该调查在UI线程上没有引发ProgressChanged
事件的原因。我怀疑你是否在应用程序初始化生命周期中过早地启动BackgroundWorker
,这可能会导致竞争条件,如果在{NullReferenceException
之前引发第一个ProgressChanged
事件,可能会txtPastes
{{1}} {1}}文本框已初始化。
答案 1 :(得分:2)
嗯,这当然应该是有效的。您的代码段中不会显示此异常的原因。重要的是启动BackgroundWorker的位置和时间。它的RunWorkerAsync()方法使用SynchronizationContext.Current属性来确定执行ProgressChanged事件处理程序所需的线程。
以下情况可能会出错:
答案 2 :(得分:1)
确保从UI线程启动BackgroundWorker
;如果这样做,将在该线程上引发ProgressChanged
事件,并且不会发生异常。
答案 3 :(得分:0)
如果您想更新GUI,例如TextBox,您应该阅读本文: