在线程中访问用户界面

11

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

如何在线程中访问UI。

6个回答

23

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

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

绝对是我遇到的最简单的方法,而且我尝试过很多UI更新线程的解决方案。得到了我的赞同。 - GONeale
你因使用最少的文字并展示最清晰的例子/解释而获胜。赞! - user34537
谢谢,这是最简单的方法,节省了我的时间。 - Tirth
太好了!这样做有什么不利之处吗?不检查InvokeRequired可以吗? - Sohail

8
如果您正在使用C# 3.5,那么使用扩展方法和lambda表达式来防止其他线程更新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");

3

我假设我们在谈论WinForms?你需要有一个单一的线程来管理这个 - 创建相关控件的线程。如果你想从不同的线程中执行此操作,可以使用Control.InvokeRequired检测到,然后应该使用Control.Invoke方法将其调度到正确的线程上。搜索该属性和方法(分别)以获取一些常见的模式。


在大多数情况下,您可以安全地使用BeginInvoke(),除非您想将任何抛出的异常调度回调用线程。 - Quibblesome
在我看来,“InvokeRequired/BeginInvoke”太啰嗦了。 - Anton Gogolev

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

1
使用 Win Form 的 BackgroundWorker 类,而不是手动实现线程同步?

1

如果您想在非 UI 线程仍在运行时修改 UI,请使用 SynchronizationContext 来调度对 UI 线程的调用。否则,请使用 BackgroundWorker


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接