从c#中的另一个类和线程更新按钮属性

时间:2011-09-19 17:25:21

标签: c# .net multithreading properties

我是C#语言的新手,我将非常感谢您对以下问题的任何帮助/反馈。

基本上,我试图开发一个程序,使它有两个类class1(主线程)和class2。 class1有一个按钮,class2启动一个线程并进行一些计算。如何从class2中的线程中的class2更新class1(main)中按钮的任何属性?

这是我想做的一个例子

// CLASS 1 is a win form 
class1:form
{

public btn_click()
{
// call function startthread from class2
 btn.Enabled = false;
 startthread()
}

}
// CLASS 2 is not a winform
class2
{
 public startthread()
 {
  Thread worker = new Thread(doCalculation)
 }

 public doCalculation()
 {
  // do some calculation then
  // blahhh
  // blahhh
  // HERE I NEED SOMEHOW ENABLED MY BUTTON 
}
}

3 个答案:

答案 0 :(得分:2)

这取决于您正在使用的UI框架。例如,假设您要更新按钮上的文本。

如果您使用的是WPF,则可以使用:

class1Instance.TheButton.Dispatcher
      .BeginInvoke( (Action) () => class1Instance.TheButton.Content = "Foo" );

使用Windows窗体,您可以使用:

class1Instance.TheButton
      .BeginInvoke( (Action) () => class1Instance.TheButton.Text = "Foo" );

答案 1 :(得分:2)

您必须将修改代码带回主线程,无论其WPF或Winforms,对UI的跨线程访问是明确禁止(通常)还是强烈劝阻和错误。

有很多方法可以做到这一点,在Winforms中我通常使用Control.Invoke,如下所示:

public void UpdateMyTextBox(string NewText) 
{
    if(InvokeRequired)
       Invoke(new Action<string>(UpdateMyTextBox), NewText);
    else
       myTextBox.Text = NewText;
}

在此示例中,InvokeRequired属性将检查是否在UI线程上调用它,如果没有,我们将调用Invoke将请求放入UI线程。< / p>

在WPF中,您会注意使用Dispatcher,并且以非常类似的方式执行此操作:

public void UpdateMyWpfTextBox(string NewText)
{
    if(!CheckAccess())
       Dispatcher.Invoke(new Action<string>(UpdateMyWpfTextBox), NewText);
    else
       myTextBox.Text = NewText;
}

答案 2 :(得分:0)

不确定你在这里尝试做什么,但考虑到问题,这是我能想出的最佳答案。我将假设这是一个winforms应用程序

Class2需要引用Class 1中的按钮。所以你需要将它传递给它。

Class2引用该按钮后,您可以尝试将该属性修改为

btn.Text = "New Text";

我将再次假设你已尝试过这条路线,遇到异常,所以你发布了你的问题。你得到异常的原因是你的btn和你的class2在不同的线程中运行。要解决这个问题,您可以在按钮上调用invoke。我经常这样处理。

private void SetButtonText(string newText) {
    if (btn.InvokeRequired) {
        Invoke((MethodInvoker)(() => SetButtonText(newText)));
    }
    else {
        btn.Text = newText;
    }
}