Search code examples
c#multithreadingwinformscontrolsinvoke

C# Invoke button control on separate thread


I have seen a lot of questions about how to edit controls on c# form from a different thread but none make much sense to me. I understand that you can not change any UI from another thread than it's main. To make this work you have to use invoke and from there safely edit the control?

I have a button that starts writing in a file and the moment you press the button the button itself gets disabled so you can not start multiple threads that do exactly the same. When the writing is done I want the button to be available again but I can not get it working on this other thread.

I have this as the Generate_Click event from the form.

private void Generate_Click(object sender, EventArgs e)
{
    Generate.Enabled = false;

    int x = 512;
    int y = 512;

    MBrot mbrot = new MBrot(x, y);

    PB_Update lb = new PB_Update(0, y, Generator_PB, Generate, mbrot, this);
    lb.Start();
}

And this is in PB_Update.cs the ThreadWork() function, when the while loop is done the writing to the file is done and so is the thread so its ended and given a messagebox with "finished" now as last the button needs to be enabled again.

public void ThreadWork()
{
    while (true)
    {
        if (currValue_ >= maxValue_)
            break;

        ThreadTick();
    }

    mb_.StopBrot();
    t_.Interrupt();

    MessageBox.Show("Finished!");
    Generate_.Enabled = true;
}

Solution

  • For WinForms you can execute directly on the thread which the control was created on through the Control.BeginInvoke method, you can use Control.Invoke as well but, Control.BeginInvoke is preferred for UI operations as it will execute asynchronously.

    public void ThreadWork()
    {
        while (true)
        {
            if (currValue_ >= maxValue_)
                break;
    
            ThreadTick();
        }
    
        mb_.StopBrot();
        t_.Interrupt();
    
        MessageBox.Show("Finished!");
        Generate_.BeginInvoke((Action)delegate()
        {
            Generate_.Enabled = true;
        });
    }