C# - Update controls from other threads

By , 9/5/2012
(1 ratings)
Anyone who has ever worked with threads is familiar with this problem: A longer lasting calculation is separated out into a thread and of course the user should be informed about the progress of the calculation. This can not be done out of the worker thread, because controls can only be updated inside from their own UI thread. An alternative is the .NET framework backroundworker, but that does not increase the code readability and fragments one contiguous block of code into several functions.
However, there is an elegant solution for this:

Author: Stefan Knoll, translation by Michael List
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsApplication8
{
  static class Program
  {
    [STAThread]
    static void Main()
    {
      Application.Run(new TheForm());
    }

    public class TheForm : Form
    {
      Label label1;
      Button button1;

      public TheForm()
      {
        label1 = new System.Windows.Forms.Label();
        label1.Location = new System.Drawing.Point(102, 14);
        label1.Size = new System.Drawing.Size(130, 13);

        button1 = new System.Windows.Forms.Button();
        button1.Location = new System.Drawing.Point(12, 9);
        button1.Size = new System.Drawing.Size(75, 23);
        button1.Text = "Start";
        button1.Click += new System.EventHandler(this.button1_Click);
        Controls.AddRange(new Control[] { label1, button1 });
      }

      private void button1_Click(object sender, EventArgs e)
      {
        // Threadpool processes DoIt
        System.Threading.ThreadPool.QueueUserWorkItem(DoIt);
      }

      private void DoIt(object dummy)
      {
        int i = 1;
        bool Cancel = false;

        while (Cancel == false)
        {
          // Sleeps 1 second for demonstration purposes
          System.Threading.Thread.Sleep(1000);

          // This is a so-called generic delegate that allows
          // full access to the UI inside the block.
          MethodInvoker LabelUpdate = delegate
          {
            // Inside this block Controls and Forms
            // can be accessed, new Windows may be
            // created etc...
            label1.Text = i.ToString() + " laps completed.";
          };

          Invoke(LabelUpdate);

          if (i % 5 == 0)
          {
            MethodInvoker QuestionDelegate = delegate
            {
              // Prompts are possible too
              if (MessageBox.Show("Another lap?", "Question", MessageBoxButtons.YesNo) == DialogResult.No)
                Cancel = true;
            };
            Invoke(QuestionDelegate);
          }
          i++;
        }
      }
    }
  }
}

Comments

 

Log in, to comment!