Page 1 of 1

Cross thread calls made easy Cross-thread operation not valid? No problem!

#1 Imdsm  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 103
  • View blog
  • Posts: 362
  • Joined: 21-March 09

Posted 29 August 2010 - 08:55 AM

Imdsm's Tutorial to cross thread calls

We've all had the problem, we're trying to do something and the form locks up, so we decide it's come to that time where we have to use another thread. Great, spaghetti code awaits. We get a coffee and we set to, eventually coming up with an awesome multi-threaded solution which keeps our form redrawing whilst we process what we're processing... except for when we try to update the form and get the dreaded Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on.

It may seem the quickest fix, but please don't under any circumstance use this recipe for disaster, ever.

Form1.CheckForIllegalCrossThreadCalls = false; // this is bad!


The situation isn't as dire as it first seems, read on and you'll see how to quickly fix this. In no time it'll become second nature. The first snippet applies if you have to pass parameters to a control, for example, you want to write text to a textbox:

using System;
using System.Windows.Forms;
using System.Threading;
 
namespace CrossThreadCalls
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private delegate void ObjectDelegate(object obj);        
 
        private void button1_Click(object sender, EventArgs e)
        {
            // first thing we do is create a delegate pointing to update method
            ObjectDelegate del = new ObjectDelegate(UpdateTextBox);
 
            // then simply enough, we invoke it
            del.Invoke("Hello from button1_Click!");
 
            // if we wanted to create a thread to use it, we'd use a
            // params threadstart and pass the delegate as an object
            Thread th = new Thread(new ParameterizedThreadStart(WorkThread));
            th.Start(del);
        }
 
        private void WorkThread(object obj)
        {
            // we would then unbox the obj into the delegate
            ObjectDelegate del = (ObjectDelegate)obj;
 
            // and invoke it like before
            del.Invoke("Hello from WorkThread!");
        }
 
        private void UpdateTextBox(object obj)
        {
            // do we need to switch threads?
            if (InvokeRequired)
            {
                // we then create the delegate again
                // if you've made it global then you won't need to do this
                ObjectDelegate method = new ObjectDelegate(UpdateTextBox);
 
                // we then simply invoke it and return
                Invoke(method, obj);
                return;
            }
 
            // ok so now we're here, this means we're able to update the control
            // so we unbox the object into a string
            string text = (string)obj;
 
            // and update
            textBox1.Text += text + "\r\n";
        }
    }
}


Now lets say you simply want to run a method which doesn't take any arguments, things get much easier now. As with before we invoke the method, but there is no need for delegates:

using System;
using System.Windows.Forms;
using System.Threading;
 
namespace TestApp2
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }  
 
        private void button1_Click(object sender, EventArgs e)
        {
            // no delegates are needed here
            UpdateTextBox();
 
            // just to show what it'd be like from another thread
            // we create a standard thread without params
            Thread th = new Thread(new ThreadStart(WorkThread));
            th.Start();
        }
 
        private void WorkThread()
        {
            // we have no params, so just call the method
            UpdateTextBox();
        }
 
        private void UpdateTextBox()
        {
            // do we need to switch threads?
            if (InvokeRequired)
            {
                // slightly different now, as we dont need params
                // we can just use MethodInvoker
                MethodInvoker method = new MethodInvoker(UpdateTextBox);
                Invoke(method);
                return;
            }
 
            // as we didn't take a param, we just update
            textBox1.Text += "Hello world!\r\n";
        }
    }
}


So as you see, it's actually quite easy.

If you're having difficulties, come and ask us in the Dream.In.Code C# corner.

For more tutorials and code, visit my blog: http://imdsm.blogspot.com/

Is This A Good Question/Topic? 4
  • +

Replies To: Cross thread calls made easy

#2 skybomb0  Icon User is offline

  • D.I.C Head

Reputation: 10
  • View blog
  • Posts: 92
  • Joined: 12-May 10

Posted 31 August 2010 - 12:34 PM

Thanks for the tutorial. Your simple example cleared up a few things. I will definately be keeping this code in a safe place.
Was This Post Helpful? 1
  • +
  • -

#3 Imdsm  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 103
  • View blog
  • Posts: 362
  • Joined: 21-March 09

Posted 03 September 2010 - 04:21 AM

Glad it helped. Things can get confusing especially when you're tasked with using delegates, threads and invoking inside a functioning application, so a quick look at the basics always helps!
Was This Post Helpful? 0
  • +
  • -

#4 GonSoft  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 12-October 11

Posted 13 February 2012 - 10:32 AM

nice explanation ... thanks a lot my friend :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1