0
 private void btnCount_Click(object sender, EventArgs e)
    {        
        Thread thread = new Thread(FuncX);
        thread.Start();         

        FuncY();
    }

    public void FuncX()
    {
        this.Invoke(new MethodInvoker(delegate
        {
            //put UI thread code here.
            //you can assign local variables values from the main thread in here as well. They are both accessible.
            lblThreadDisplayX.Text = "0";
            int x = Convert.ToInt32(lblThreadDisplayX.Text);
            for (int j = 0; j < loopTime; j++)
            {
                x++;
                lblThreadDisplayX.Text = x.ToString();
                Thread.Sleep(5);
                Update();
            }
        }));           
    }

    public void FuncY()
    {
        lblThreadDisplayY.Text = "0";
        int y = Convert.ToInt32(lblThreadDisplayY.Text);
        for (int i = 0; i < loopTime; i++)
        {
            y++;
            lblThreadDisplayY.Text = y.ToString();
            Thread.Sleep(5);
            Update();
        }
    }
}
}

Above is my code for a tester I'm working on to get threading to work. There are 2 labels, X and Y, which call functions X and Y, and in those functions, the text of the labels are incremented by 1 repeatedly. However, I want to do this simultaneously. When I try to make a thread out of FuncX, it says that it cannot access an object created in another Thread and crashes. I used the lock(){} statement, but it didn't work. What can I do to have the label's text change inside of a thread?

Edit: Updated the Code, and this is with a Windows Form in Visual Studio 2008. Adding in a Timer to the thread with FuncX in it causes FuncY to execute first, then FuncX's thread.

user3215251
  • 239
  • 1
  • 16
  • I think this is because the UI only has one thread and you are trying to access it on different threads at the same time, check out BackgroundWorker or the Task Parallel Library – reggaeguitar May 07 '14 at 18:54
  • 2
    Just Google the exception you get. You'll easily find the answer. – Mohammad Dehghan May 07 '14 at 18:55
  • 1
    You can't modify the UI from a non-UI thread. – codeConcussion May 07 '14 at 18:55
  • 2
    http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Cemafor May 07 '14 at 18:56
  • Use [BeginInvoke](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke%28v=vs.110%29.aspx) to change the `Text` property. – Alessandro D'Andria May 07 '14 at 18:56
  • It is a form. What about timers? I always get to write services or web and never get to use those useful little things. – Anthony Horne May 07 '14 at 18:56
  • The link too the other thread isn't terribly helpful. A lot of things are going on in the selected code that I don't know where to put them. I don't understand how to apply them to a thread that ticks up while you do other things. – user3215251 May 07 '14 at 19:03

1 Answers1

3

Your problem is twofolde:

1- should not be sharing controls or variables between threads without looking at locking them first. You are technically in a Race Scenario at that point which can cause havoc.

2- The labels were created on the Main UI thread. In order to access them from within a thread, you have to Invoke the main thread to get at it, from within your sub threads... which, again, circumvent the whole point of threading since you're also using the labels to "globally store your variables".

But if you must, here's how to access the labels within your threads:

To execute code from within the thread or access elements:

this.Invoke(new MethodInvoker(delegate
{
    //put UI thread code here.
    //you can assign local variables values from the main thread in here as well. They are both accessible.
}));

To only extract the value of an object or property of an object (i inserted placeholders for you here, this call is not a literal call and you must adapt it to your needs):

TypeName yourvar = (TypeName)this.Invoke(new Func<TypeName>(() => UICode here as TypeName));

Hope this helps you!

MaxOvrdrv
  • 1,780
  • 17
  • 32
  • I tried the one you posted above, and it worked! However, adding in a Sleep Timer. I used FuncX as my thread, but it triggers AFTER FuncY, which is called AFTER the Thread start for FuncX. – user3215251 May 07 '14 at 19:15
  • how can you say for sure that it triggers after FuncY? – MaxOvrdrv May 07 '14 at 19:31
  • I added in a timer. FuncY did the increment first, making LabelY go up from 0 to 2000, then LabelX went from 0 to 2000 with FuncY was done. – user3215251 May 07 '14 at 19:48
  • that is because you are basically pausing the UI thread (just saw your code update sorry)... because you put the thread.sleep inside the invoker, you are dealing with the UI thread and not your local thread. put the sleep call outside of the invoker instad. – MaxOvrdrv May 08 '14 at 18:54