【问题标题】:C# GUI Application, Another class from another thread updating the UIC# GUI 应用程序,来自另一个线程的另一个类更新 UI
【发布时间】:2010-10-30 07:49:39
【问题描述】:

我一直在研究如何做到这一点大约一个星期,但我仍然不确定正确的方法,在某些示例中,我看到在其他示例中使用了 Thread 类我看到使用了 Invoke,这让我感到困惑出价。

我有一个 c# 中的 GUI 程序,其中包含一个文本框,用于向用户提供信息。

我面临的问题是我不确定如何将文本从另一个线程上运行的另一个类附加到 textBox。如果有人可以向我展示一个工作示例,那将对我有很大帮助。

最好的问候!

【问题讨论】:

  • 我以为您在谈论 WPF GUI?你是?你应该指定..

标签: c# multithreading user-interface class


【解决方案1】:

简单:

MainWindow.myInstance.Dispatcher.BeginInvoke(new Action(delegate() {MainWindow.myInstance.myTextBox.Text = "some text";});

WHERE MainWindow.myInstance 是设置为 MainWindow 实例的公共静态变量(应在构造函数中设置,并且在构造实例之前为 null)。

好吧,一行就这么多,让我来复习一下:

当您想要更新 UI 控件时,正如您所说,您必须从 UI 线程进行。有一种内置方式可以将委托(一种方法)传递给 UI 线程:Dispatcher。我使用了 MainWindow.myInstance,它(作为所有 UI 组件)包含对 Dispatcher 的引用 - 您也可以在自己的变量中保存对 Dispatcher 的引用:

Dispatcher uiDispatcher = MainWindow.myInstance.Dispatcher;

一旦你有了 Dispatcher,你可以通过 BeginInvoke() 的 Invoke() 传递一个委托在 UI 线程上运行。唯一的区别是 Invoke() 只会在委托运行后返回(即在您的情况下,TextBox 的文本已设置),而 BeginInvoke() 将立即返回,因此您调用的其他线程可以继续(调度程序将运行尽快让您的代表尽快处理,这可能会立即生效)。

我在上面传递了一个匿名委托:

delegate() {myTextBox.Text = "some text";}

{} 之间的位是方法块。这被称为匿名,因为只创建了一个并且它没有名称 - 但我可以实例化一个委托:

Action myDelegate = new Action(UpdateTextMethod);

void UpdateTextMethod() 
{
    myTextBox.Text = "new text";
}

然后通过了:

uiDispatcher.Invoke(myDelegate);

我还使用了内置委托的 Action 类,但您可以创建自己的 - 您可以在 MSDN 上阅读有关委托的更多信息,因为这有点离题..

【讨论】:

  • 这完全是正确的答案。但是请注意,BeginInvoke 会将您的委托操作添加到队列中,因此 UI 将在“可以”时更新。因此,做所有应该在委托中排序的事情。
  • 另一条评论:BeginInvoke 是一个在框架 3.5 出来时参数发生变化的方法,所以 IntelliSense 文档中关于它们的信息不正确(在 google 上查找它,每个人都对此感到愤怒)。您可以传递一个优先级来帮助 UI 决定是否应该立即更新,或者是否对BeginInvoke(DispatcherPriority.Render, new Action(yourDelegate)) 不那么重要。
  • 是的 - 即使使用 Invoke() 委托也会被放入队列中,尽管队列应该(以保持 UI 响应)只包含小的快速进程,这就是为什么我说可能会马上..
  • 是的,您可以指定优先级,但它是可选的(该方法已重载)并且 99% 的时间都是默认值:DispatcherPriority.Normal,无论如何都是您想要的。
  • 谢谢,但我似乎无法使用 Dispatcher 类。我必须添加参考才能使用它吗?
【解决方案2】:

听起来您正在使用后台线程进行处理,但想要保持 UI 响应? BackgroundWorker 听起来像门票:

BackgroundWorker 类允许您 在单独的设备上运行操作, 专用线程。耗时的 下载和数据库等操作 交易可能会导致您的用户 界面(UI)看起来好像 他们停止响应 跑步。当您想要响应式 UI 时 你面临着长时间的延误 与此类操作相关的, BackgroundWorker 类提供了一个 方便的解决方案。

【讨论】:

  • 我不明白 BackgroundWorker 的相关性 - 他已经在另一个线程上运行...
  • 在您解释事件处理程序如何在主线程上运行之前,您不会理解这个答案。
【解决方案3】:

同样使用 BackgroundWorker。它很简单,并且消除了管理自己的线程的痛苦。更多内容可以看:http://dotnetperls.com/backgroundworker

【讨论】:

  • 后台工作线程是线程池中的一个线程,因此不是 STA 线程,所以除了抛出事件之外,您将无法从中做很多与 UI 相关的事情。
猜你喜欢
  • 2020-10-15
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多