访问线程中的UI

时间:2009-04-02 10:31:50

标签: c# multithreading user-interface

当我尝试更改UI属性(特别是启用)时,我的线程抛出System.Threading.ThreadAbortException

如何访问线程中的UI。

6 个答案:

答案 0 :(得分:19)

您可以使用BackgroundWorker,然后像这样更改UI:

control.Invoke((MethodInvoker)delegate {
    control.Enabled = true;
});

答案 1 :(得分:7)

如果您使用的是C#3.5,那么使用扩展方法和lambdas来阻止从其他线程更新UI非常容易。

public static class FormExtensions
{
  public static void InvokeEx<T>(this T @this, Action<T> action) where T : Form
  {
    if (@this.InvokeRequired)
    {
      @this.Invoke(action, @this);
    }
    else
    {
      action(@this);
    }
  }
}

现在,您可以在任何表单上使用InvokeEx,并且可以访问不属于Form的任何属性/字段。

this.InvokeEx(f => f.label1.Text = "Hello");

答案 2 :(得分:3)

我假设我们在这里谈论WinForms?您需要有一个单独的线程来管理这个 - 创建相关控件的线程。如果要从可以使用Control.InvokeRequired检测到的其他线程执行此操作,则应使用Control.Invoke方法将其编组到正确的线程上。谷歌那个属性和方法(分别)为此做了一些常见的模式。

答案 3 :(得分:1)

如何使用Win Forms BackgroundWorker类而不是手动线程同步实现?

答案 4 :(得分:1)

如果要在非UI线程仍在运行时修改UI,请使用SynchronizationContext封送对UI线程的调用。否则,请使用BackgroundWorker

答案 5 :(得分:1)

void button1_Click( object sender, EventArgs e ) {
    var thread = new Thread( ParalelMethod );
    thread.Start( "hello world" );
}
void ParalelMethod( object arg ) {
   if ( this.InvokeRequired ) {
       Action<object> dlg = ParalelMethod;
       this.Invoke( dlg, arg );
   }
   else {
       this.button1.Text = arg.ToString();
   }
}