Eliminate cross-flow
I have a problem for a while
this line:
txtPastes.Text = (string)e.UserState;
throws a cross thread exception and I haven't found any solution
txtPastes
- text field
GuiUpdate
- BackgroundWorker
lstAllPastes
- list of strings
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)
{
}
source to share
You cannot update a UI control from any thread other than the UI thread. As a rule, BackgroundWorker
will take care of the correct display of events ProgressChanged
and RunWorkerCompleted
in the UI thread. Since that doesn't seem to be the case here, you could marshal your UI update logic to the UI thread yourself using the method Invoke
:
txtPastes.Invoke(new Action(() =>
{
// This code is executed on the UI thread.
txtPastes.Text = (string)e.UserState;
}));
If you are using WPF, you need to call Invoke
on the control manager:
txtPastes.Dispatcher.Invoke(new Action(() =>
{
txtPastes.Text = (string)e.UserState;
}));
Update . As Thomas Leveque and Hans Passant mentioned, you should figure out the reason why your event ProgressChanged
does not fire on the UI thread. My suspicion is that you are starting BackgroundWorker
too early in the application's initialization lifecycle, which could lead to race conditions and possibly NullReferenceException
if the first event ProgressChanged
is raised before the text field is initialized txtPastes
.
source to share
Well, that should work, of course. The reason for this exception does not appear in your snippet. What matters is where and when the BackgroundWorker runs. Its RunWorkerAsync () method uses the SynchronizationContext.Current property to figure out which thread should execute the ProgressChanged event handler.
It can go wrong if:
- You started BGW too early, before calling Application.Run (). Winforms or WPF do not yet have the ability to install their own sync provider.
- You have called BGW's RunWorkerAsync () method on a worker thread. Only marshaling is supported for the UI thread, the message loop is an essential component to make executable code in a different thread.
- The form containing the txtPastes control was created on a different thread. When running BGW on a UI thread that still does not match thread consumption
- The form's Show () method is called on another thread. Which creates its own windows window on the wrong thread.
source to share