How do I access variables from a different thread?

16,232

Solution 1

Accessing a control from different threads

In WinForms App you can ony access directly a Control from the thread it was created. To do such a task you will need to use InvokeRequired property of a control to see if you must use Invoke inorder to force a call of the action from the original thread.

A public method that might be accessed from any thread including the original would look like this:

public void run() {
    if (label1.InvokeRequired) //Is this method being called from a different thread
        this.Invoke(new MethodInvoker(()=> label1.Text = CONNECTING));
    else //it's cool, this is the original thread, procceed
        label1.Text = CONNECTING;
}


But if you are absolutly sure that run() method will be called only from the thread, consider not even checking if InvokeRequired and immediatly call Invoke

Further information: http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

Stopping a thread in progress

  • Simples is to use t1.Abort(); method of a Thread. This will throw and exception forcing it to stop where ever it was. this is great for threads that do not do any long processing so stopping it won't cause any problems.

  • If you do do proccesing in your thread, which means you can't just stop it in the middle then I suggest you to use a boolean that will indicate that the thread must cancel ASAP.

private bool isCancelRequired = false;
public void run() {
     while(true) {
         //do long processing..
         if (isCancelRequired)
            break;
     }
} 

Solution 2

Try using BeginInvoke:

public void run() 
{
    label1.BeginInvoke(new Action(() =>
    {
        label1.Text = CONNECTING;
    }));
}

Only the UI thread can update UI elements in a Windows Forms app. Other threads need to use BeginInvoke to update the UI.

ORGINAL: i assumed this was a WPF app and said to use this.Dispatcher, but Dispatcher isn't in Windows Forms apps.

Share:
16,232
Adam
Author by

Adam

(my about me is currently blank)

Updated on June 04, 2022

Comments

  • Adam
    Adam almost 2 years

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

    Code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            string CONNECTING = "Connecting to server...";
            string GETTING_DATA = "Getting data...";
            string CONNECT_FAIL = "Failed to connect!";
            string CONNECT_SUCCESS = "Connection established!";
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Thread t1 = new Thread(run);
                t1.Start();
            }
    
            public void run() {
                label1.Text = CONNECTING;
            }
        }
    }
    

    How do I properly fix this? I've tried using CheckForIllegalCrossThreadCalls = false; but that obviously causes errors.

    I'd also like to know how I can stop the thread, since it can't be accessed anymore outside of that function.

    Thanks in advance!