user2128702
user2128702

Reputation: 2121

About Multithreading with GUIs in c#

I was reading that example that I am going to post and what I don't understand is this: They say that if I want to perform an interaction with the GUI it has to be done by the UI thread.In other words: using the .Invoke method of the Controll class. In the example I don't understand why we are using the output.Invoke... in the GenerateRandomCharacters method where the output is being changed but in the Toggle() where the output is also being changed (its color) there is no .Invoke ? Isn't it the same?

public class RandomLetters
{
    private static Random generator = new Random(); // for random letters
    private bool suspended = false; // true if thread is suspended
    private Label output; // Label to display output
    private string threadName; // name of the current thread

   // RandomLetters constructor
   public RandomLetters( Label label )
   {
      output = label;
   } // end RandomLetters constructor

   // delegate that allows method DisplayCharacter to be called
   // in the thread that creates and maintains the GUI
   private delegate void DisplayDelegate( char displayChar );

   // method DisplayCharacter sets the Label's Text property
   private void DisplayCharacter( char displayChar )
   {
   // output character in Label
      output.Text = threadName + ": " + displayChar;
   } // end method DisplayCharacter

   // place random characters in GUI
   public void GenerateRandomCharacters()
   {
   // get name of executing thread
      threadName = Thread.CurrentThread.Name;

      while ( true ) // infinite loop; will be terminated from outside
      {
      // sleep for up to 1 second
         Thread.Sleep( generator.Next( 1001 ) );

         lock ( this ) // obtain lock
         {
           while ( suspended ) // loop until not suspended
           {
             Monitor.Wait( this ); // suspend thread execution
           } // end while
         } // end lock
         // select random uppercase letter
         char displayChar = ( char ) ( generator.Next( 26 ) + 65 );

         // display character on corresponding Label
         output.Invoke( new DisplayDelegate( DisplayCharacter ),
         new object[] { displayChar } );
      } // end while
    } // end method GenerateRandomCharacters

    // change the suspended/running state
    public void Toggle()
    {
       suspended = !suspended; // toggle bool controlling state

       // change label color on suspend/resume
       output.BackColor = suspended ? Color.Red : Color.LightGreen;

       lock ( this ) // obtain lock
       {
          if ( !suspended ) // if thread resumed
          Monitor.Pulse( this );
       } // end lock
     } // end method Toggle
  } // end class RandsomLetters

EDIT: And here it is the actual call:

public partial class GUIThreadsForm : Form
{
    public GUIThreadsForm()
    {
        InitializeComponent();
    } // end constructor

    private RandomLetters letter1; // first RandomLetters object
    private RandomLetters letter2; // second RandomLetters object
    private RandomLetters letter3; // third RandomLetters object

    private void GUIThreadsForm_Load( object sender, EventArgs e )
    {
        // create first thread
        letter1 = new RandomLetters( thread1Label );
        Thread firstThread = new Thread(
            new ThreadStart( letter1.GenerateRandomCharacters ) );
        firstThread.Name = "Thread 1";
        firstThread.Start();

        continues...

This is the way Toggle() method is being called:

private void threadCheckBox_CheckedChanged( object sender, EventArgs e )
{
    if ( sender == thread1CheckBox )
        letter1.Toggle();
    else if ( sender == thread2CheckBox )
        letter2.Toggle();
    else if ( sender == thread3CheckBox )
        letter3.Toggle();
} // end method threadCheckBox_CheckedChanged

After a checkbox control is activated in CheckedChanged event and it gets into the Toggle() method

Upvotes: 0

Views: 109

Answers (1)

Servy
Servy

Reputation: 203802

Presumably whatever is calling this class's methods is only ever calling GenerateRandomCharacters from a non-UI thread, and Toggle is only ever being called from the UI thread, hence why only GenerateRandomCharacters needs to explicitly marshal to the UI thread.

You would need to see how these methods are called to verify that.

Upvotes: 1

Related Questions