Control.InvokeRequired - Subject to a race condition

114 views Asked by At

I found a suggested solution to the cross-thread exception issue in another posting and have used it my code below, but I am finding it erratic at best. My tests indicate that it's correct operation is at the mercy of a race condition so I was hoping someone might be able to point out the obvious or provide a more robust solution.

I have a program with two simple forms, where the sole purpose of Form1 is to open Form2. Form2 only contains a RichTextBox and has code that starts a thread that accesses that RichTextBox in an arbitrary way. When execution reaches the InvokeRequired property it is usually (but not always) false, so it goes directly to the RichTextBox access where a cross-thread exception is generated. However, when I call Thread.Sleep(...) just before testing the InvokeRequired property it appears to work properly. However, I hate to use Sleep for this purpose simply because it seems like a kluge that may not always work. Is there a reliable, yet reasonable, way to do cross-thread communication? Thanks.

public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();
      var form2 = new Form2();
      form2.ShowDialog();
   }
}

public partial class Form2 : Form
{
   public Form2()
   {
      InitializeComponent();
      Thread myThread = new Thread(new ThreadStart(myStartingMethod));
      myThread.Start();
   }

   void myStartingMethod()
   {
      Test("Hello world!\n");
   }

   private delegate void myCallback(string text);
   private void Test(string text)
   {
      // If I put Thread.Sleep(...something...) here it works better.
      if (myRichTextBox.InvokeRequired)
      {
         myCallback d = new myCallback(Test);
         Invoke(d, new Object[] { text });
      }
      else
      {
         // Cross-thread exception usually occurs, but not always.
         int x = myRichTextBox.TextLength;
      }
   }
}
0

There are 0 answers