C# background worker, winform. "Cross-thread operation not valid:"

11,070

Solution 1

Q1

Your bw_doWork method is a static. This means there is only one of those methods for all instances of your class. That method cannot access instance-specific properties or fields or methods. That explains the compiler error.

If you change that method to NOT be static it will allow you to reference label1 within it.


Q2.

The syntax you refer to is a shortcut to add an event handler to that event.

It just means "Add this handler to the list of handlers for the given event." The long-handed way of doing it is with AddEventHandler.

http://msdn.microsoft.com/en-us/library/system.reflection.eventinfo.addeventhandler.aspx

Q3

The cryptic message you get at runtime indicates that you cannot update the UI objects on the non-uI thread. (The bg worker implies a different thread.) The solution is to perform the update you want on the UI thread.

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    // This is called on the worker thread
    UpdateLabel((string)e.Argument));
      ...more work here...
}

void UpdateLabel(string s)
{
    if (this.label1.InvokeRequired)
    {
        // It's on a different thread, so use Invoke.
        this.BeginInvoke (new MethodInvoker(() => UpdateLabel(s));
    }
    else
    {
        // It's on the same thread, no need for Invoke
        this.label1.Text = s;
    }
}

To learn more about it, http://msdn.microsoft.com/en-us/library/ms171728(v=vs.90).aspx

Solution 2

In the DoWork-event you should perform the work you want to be executed on a different thread, ie. "the background work that won't freeze your application".

Then you have a Progress-event (I think, something similar at least) - this is where you update your GUI, ie. change the text or your label. Don't perform any heavy work here, it's your main thread.

In your DoWork-event, ie. the background thread, you may report the progress to the main thread using a method on your BackgroundWorker object (I don't remember the name of the method, something like Report, Progress or something), the Progress-event will then be called on the main thread.

Share:
11,070
Guye Incognito
Author by

Guye Incognito

My background is in architecture (real world architecture!) Currently studying Higher Diploma in Computing conversion course in D.I.T.

Updated on June 04, 2022

Comments

  • Guye Incognito
    Guye Incognito almost 2 years

    I'm trying to get background worker functioning in the most basic way with a windows form, for instance get a background process to change text in a label.. I got the basic background worker code here.. http://www.albahari.com/threading/part3.aspx Heres the code in my form.. Trying to make it so you press a button and then background worker thread is spawned which changes text in the label

        using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Data;
        using System.Drawing;
        using System.Linq;
        using System.Text;
        using System.Windows.Forms;
    
           namespace WindowsFormsApplication4
        {
            public partial class Form1 : Form
            {
                public Form1()
                {
                    InitializeComponent();
                }
    
    
                BackgroundWorker _bw = new BackgroundWorker();
    
                 void backgroundio()
                {
                    _bw.DoWork += bw_DoWork;
                    _bw.RunWorkerAsync("Message to worker");
    
                }
    
                 void bw_DoWork(object sender, DoWorkEventArgs e)
                {
                    // This is called on the worker thread
                    label1.Text = (string)(e.Argument);        // writes "Message to worker"
                    // Perform time-consuming task...
                }
    
                 void button1_Click(object sender, EventArgs e)
                 {
                     backgroundio();
                 }
    
            }
        }
    

    For the label1.Text = (string)(e.Argument); I get this error.

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

    Thank for any help !! :)

    Actually while I'm here can somebody explain this line?

     _bw.DoWork += bw_DoWork;
    

    I dont get how += makes any sense in this context. how can you add those things?

  • Guye Incognito
    Guye Incognito almost 12 years
    Thanks! To all: I edited my question after this, Cheeso isn't mad!!
  • Cheeso
    Cheeso almost 12 years
    ok, so you've accepted the answer, but you still have a question. I will edit my answer.
  • Guye Incognito
    Guye Incognito almost 12 years
    ah! the stuff here albahari.com/threading/part3.aspx is starting to make sense to me now!! :D