-2

I have a class called Form1, which has a button in it. Now in that class I made another thread.

If I try to change the button in any way from the new thread, I get the cross-thread error/exception

new Thread(delegate ()
            {
                while (!DL.HasExited)
                {
                    Thread.Sleep(500);
                }

                File.Delete(folderBrowserDialog1.SelectedPath + @"\Steam\steamcmd.zip");
            //The code below this note is the problem
                button1.Text = "START DOWNLOADING";
                button1.Enabled = true;
            }).Start();

I need to have the code in the new Thread, because I don't want to make my program freeze when it reaches the while loop.

So how can I change the button text from a different thread?

Tom Lenc
  • 765
  • 1
  • 17
  • 41

4 Answers4

4

you cannot access ui element properties from a different thread. Use beginInvoke

button1.BeginInvoke( new MethodInvoker(() =>
{
      button1.Text = "START DOWNLOADING";
      button1.Enabled = true;
}));
chathux
  • 821
  • 8
  • 17
0

Use Invoke(). This function takes a delegate (you can pass an anonymous function too). Something like:

Invoke(() => {
    button1.Text = "START DOWNLOADING";
    button1.Enabled = true;});
dotNET
  • 33,414
  • 24
  • 162
  • 251
0

The simplest way to achieve what you want is to use the BeginInvoke function on the control:

public delegate void InvokeDelegate();

new Thread(delegate ()
{
    while (!DL.HasExited)
    {
        Thread.Sleep(500);
    }

    File.Delete(folderBrowserDialog1.SelectedPath + @"\Steam\steamcmd.zip");
    //The code below this note is the problem
    button1.BeginInvoke(new InvokeDelegate(InvokeMethod));

}).Start();

public void InvokeMethod()
{
   button1.Text = "START DOWNLOADING";
   button1.Enabled = true;
}
superpuccio
  • 11,674
  • 8
  • 65
  • 93
  • 1
    `BeginInvoke()` can potentially create a race condition here. He'd better live happily with `Invoke()`. – dotNET Aug 13 '15 at 16:46
  • it says that it can't convert lambda expressions to Delegate because it's not a delegate type or something.. – Tom Lenc Aug 13 '15 at 16:51
0

Threads are not meant to mess with each other's memory space - thus, your attempt to simply change the text will fail. However, there are 3 solutions I could think of:

  • Using invoke()

As others mentioned a few seconds before I did, you could use invoke to change the text in another form. However, if you'd like any more communication between the threads, this would be inefficient.

  • Using shared resources

In order to converse between threads, you can use a common resource that will be used for their communication. A very basic example of this is writing from the thread to a text file the text you want the button to display, and reading it each few seconds from the other thread and checking for changes. There are some better ways to do this, this is just an example. If you'd like me to show you an example of this method, ask for it and I'll gladly provide it.

  • Using processes instead of threads

Proccesses and threads both allow the multytasking you need, however, processes can interfere with each other. There are some more diffrences you should read about before making this decision, which leaves it up for you - which do you think is more fit for each one of these, a process or a thread? I'll happily provide an example of the usage of proccesses if you'd like me too, as well.

Good luck :)

Community
  • 1
  • 1
A. Abramov
  • 1,823
  • 17
  • 45