C# – How to fix “Action being performed on this control is being called from the wrong thread”?

When we populate the data in the control, if the data is big, usually we put the data population logic in the thread to execute it asynchronously. We need to be cautious when we do this data population from another thread. Because, we can not use the controls directly in different threads. This has to be marshaled properly before we pass the control between the threads. If we miss to do this properly, we will see below Error message;

--------------------------- 
TreeView - Demo
---------------------------
Action being performed on this control is being called from the wrong thread. Marshal to the correct thread using Control.Invoke or Control.BeginInvoke to perform this action.
---------------------------
OK 
---------------------------

Through this article, we are going to discuss how to reproduce this error using TreeView control and also discuss how to fix this.

Reproducing the above error

Step 1. Create a C# Windows Forms Application and place a TreeView control on the Form.

Step 2. Let’s populate the random values in the control. And the population logic, we will place in a thread. The code looks like below;

        Task task = Task.Run( () => PopulateData());

        private void PopulateData()
        {
            Random rand = new Random();
            TreeNode node = treeViewControl.Nodes.Add("Parent");

            for (int i = 0 ; i < 10000 ; i++ ) // some kind of long operation
                node.Nodes.Add(rand.Next().ToString());
        }

Step 3. Run the program and you will see the above Error message; as we are using separate thread to populate the data. Better way is,  caught the exception, and display the message; it looks like below.

InvalidOperationException was caught
InvalidOperationException was caught

How to fix the above issue?

Step 4. We will use control’s BeginInvoke() method to populate the data asynchronously; instead of putting the data population logic to run in a separate thread. This method is a thread safe; it properly handles the marshaling, hence we can use this method in our sample to populate the data.

One variance of BeginInvoke() method, takes delegate as an argument. So, we will invoke this method to invoke the data population logic and we pass delegate as an argument. The delegate will points to the function where we placed data population logic; in this example, it is PopulateData() method.

We re-write the above code as below;

public delegate void FunctionDelegate();

treeViewControl.BeginInvoke(new FunctionDelegate(PopulateData));

Step 5. Now, re-run the program and observe that; the program successfully compiled and populate the data in the TreeView control. The screenshot of it, looks like below;

TreeView control - Populate data
TreeView control – Populate data

(Raju)

Add a Comment

Your email address will not be published.