Cross Thread Call Exception in Win-Form Based Application

In windows based multi-threaded application, many times you may receive an Exception of Cross-Thread call exception (InvalidOperation Exception). Exception message is as shown below:

Cross-thread operation not valid: Control 'Control1' accessed from a thread other than the thread it was created on.

Scenario: Consider an application in which a child form will be opened from the MDI parent and a control called "label1" will be updated by a function written in the same form class and called from the MDI with different thread as shown below:



Code for MDI Parent:

namespace CTCE1
{
    public partial class MDIParent1 : Form
    {
        public MDIParent1()
        {  InitializeComponent(); }
        Form1 frm;
        public void callDemoMenu_Click(object sender,EventArgs e)
        {
              Thread t = new Thread(new ThreadStart(set));
               t.Start();

        }
        private void CrossThreadMenu_Click(object sender, EventArgs e)
        {
            frm = new Form1();
            frm.MdiParent = this;
            frm.Show();
        }        private void set()
        {
            frm.setValue();
        }
    }
}

Code For Child Form (With Cross Thread Call Exception)

*There is a Label control called "label1" in the child form which is to be updated

namespace CTCE1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            label1.Text = "Set Value";
        }
        public void setValue()
        {
            label1.Text = "Changes Applied Successfully";
        }
    }
}





Now from the above code we will get exception that Cross-Thread Operation. This kind or exceptions occurs when any control is created by one thread and another thread is trying to update the content of the UI control. Steps to overcome this problem is written below:

To over come this step we have to invoke the method with respect to the control which has to be updated.
New code to update the control is written below:

Code of the Child Form (No Exception)

namespace CTCE1
{
    public partial class Form1 : Form
    {
        public delegate void setter();   //this delegate will be used to invoke the method to update the control
        public Form1()
        {
            InitializeComponent();
            label1.Text = "Set Value";
        }
        public void setValue()
        {
            if (label1.InvokeRequired)
            {
                setter s = new setter(setValue);
                label1.Invoke(s);
            }
            else
            {
                try
                {
                    label1.Text = "Changes Applied Successfully";
                }
                catch (Exception e)
                {
                 }
            }
        }
    }
}



Now you will see changes to the control has been made successfully by invoking the mehtod.

No comments:

Post a Comment