C#在单独的线程上调用按钮控件

时间:2015-03-17 19:56:32

标签: c# multithreading winforms controls invoke

我已经看到很多关于如何从不同的线程编辑c#表单控件的问题,但没有一点对我有意义。我知道你不能从另一个线程改变任何UI而不是它的主要。要完成这项工作,你必须使用invoke并从那里安全地编辑控件?

我有一个开始在文件中写入的按钮,当你按下按钮时按钮本身被禁用,所以你不能启动完全相同的多个线程。写完后,我希望按钮再次可用,但我不能让它在另一个线程上工作。

我将此作为表单中的Generate_Click事件。

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();
}

这是在PB_Update.cs中的ThreadWork()函数,当while循环完成时,对文件的写入完成,因此线程结束并给出一个消息框“完成”现在作为最后一个按钮需要再次启用。

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

        ThreadTick();
    }

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

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

3 个答案:

答案 0 :(得分:4)

对于WinForms,您可以直接在通过Control.BeginInvoke方法创建控件的线程上执行,也可以使用Control.Invoke但是,Control.BeginInvoke是UI操作的首选。

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

        ThreadTick();
    }

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

    MessageBox.Show("Finished!");
    Generate_.BeginInvoke((Action)delegate()
    {
        Generate_.Enabled = true;
    });
}

答案 1 :(得分:1)

这是一个启动异步任务的简单示例,该任务禁用按钮5秒钟然后再次启用它。同时,UI的其余部分功能齐全。

请注意,此async方法与Generate_Click事件存在于同一个类中,并在UI线程上运行。这意味着它可以启用和禁用按钮。但是长时间运行的任务在一个单独的线程上执行,因此它不会锁定UI。

希望此示例为您提供修改自己代码的基础:

private void Generate_Click(object sender, EventArgs e)
{
    DisableButton(sender as Button, 5);
}

private async void DisableButton(Button sender, int secondsToDisable)
{
    sender.Enabled = false;

    // In your code, you would kick off your long-running process here as a task
    await Task.Run(()=>Thread.Sleep(TimeSpan.FromSeconds(secondsToDisable)));

    sender.Enabled = true;
}

答案 2 :(得分:0)

不知何故,获取对承载generate_按钮的表单的引用(让我们称之为myform)。然后,在ThreadWork的底部:

myform.Invoke(new Action(() => {
    myform.SetGenerateEnabled();
}));

然后在表单中创建适当启用按钮的方法。 (我使用了一种方法而不是直接更新按钮,因此您不会公开显示该按钮。)

这会在myform的线程{ ... }内执行命令,这是一个UI线程,因为它是UI。至少,这是我的理解。这就是我从其他线程更新所有UI的方法。