Ramifications of CheckForIllegalCrossThreadCalls=f

2020-02-12 07:51发布

问题:

I recently updated an application from VS2003 to VS2008 and I knew I would be dealing with a host of "Cross-thread operation not valid: Control 'myControl' accessed from a thread other than the thread it was created on" I am handling this in what I beleive is the correct way (see code sample below). I am running into numerous controls that are going to need a similar fix. Not wanting to have similar code for every label, textbox etc.. that are being accessed by a non UI thread. What are the ramifications of just setting the CheckForIllegalCrossThreadCalls = false for the entire app?

I found a CodeProject article with various workarounds and a warning at the bottom to NOT set the property. I am looking for other opinions/experiences on this issue.

private void ShowStatus(string szStatus)
{
    try
    {
        if (this.statusBar1.InvokeRequired) { BeginInvoke(new MethodInvoker(delegate() { ShowStatus(szStatus); })); }
        else { statusBar1.Panels[0].Text = szStatus; }
    }
  catch (Exception ex)
  {
    LogStatus.WriteErrorLog(ex, "Error", "frmMNI.ShowStatus()");
  }
}

I found another article with some possible solutions SO Question 2367718

回答1:

When you're not debugging, you'll still have problems.

From the documentation of Control.CheckForIllegalCrossThreadCalls:

Note that illegal cross-thread calls will always raise an exception when an application is started outside the debugger.

You'll need to correct the problems.

That being said, you mentioned:

Not wanting to have similar code for every label, textbox etc.. that are being accessed by a non UI thread.

I would reconsider this stance. You should try to move the logic running on a separate thread into separate methods or classes, which will in turn make marshaling the calls back into the UI much simpler. Over time, this will make your code much more reliable and maintainable.

Note that you can use Control.Invoke to marshal a whole set of calls to the UI in one call, too, instead of doing each single set operation individually. There really shouldn't be that many of them, when you finish.

Edit:

For example, it sounds like you're loading the data. Say you have (on your background thread), your data loading method:

var myData = LoadData();
this.Invoke( new Action( () =>
    {
        // Just set all of your data in one shot here...
        this.textBox1.Text = myData.FirstName;
        this.textBox2.Text = myData.LastName;
        this.textBox3.Text = myData.NumberOfSales.ToString();
    }));


回答2:

The remarks section of the documentation for CheckForIllegalCrossThreadCalls makes it pretty clear that doing so is not a good idea

When a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results. A common invalid thread activity is a call on the wrong thread that accesses the control's Handle property. Set CheckForIllegalCrossThreadCalls to true to find and diagnose this thread activity more easily while debugging. Note that illegal cross-thread calls will always raise an exception when an application is started outside the debugger.