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)
    {

    }

      

0


source to share


4 answers


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

.

+5


source


Make sure you start BackgroundWorker

from the UI thread; if you do, the event ProgressChanged

will be raised on that thread and no exception will be thrown.



+1


source


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.
+1


source


If you want to update your GUI like TextBox you should read this article:

Refresh GUI from another thread

0


source







All Articles