如何使用后台线程中的信息更新WPF窗口?

我正在创建一个wpf应用程序,它在后面执行许多任务,但仍然需要UI响应并显示各种后台任务的状态。 它还可以选择不显示UI,在这种情况下,应该丢弃状态消息而根本不创建主窗体的实例。

我试图删除

StartupUri="MainWindow.xaml"

来自App.xaml。 然后,在App.xaml.cs中,我有

`

  public App() { Startup += new StartupEventHandler(App_Startup); } void App_Startup(object sender, StartupEventArgs e) { // Code which loads application settings is here if (pf.ShowUI) { MainWindow mainWindow = new MainWindow(); mainWindow.Show(); } // The background processes will begin here. }` 

如有必要,这将显示主窗体并启动所有后台进程。 这部分有效。

为了从后台向UI发送消息,我实现了一个非常基本的信使:

`

 internal interface IMessageHandler { void ReceiveMessage(string message); } internal class Messenger { private static List _handlers; internal static void AddHandler(IMessageHandler handler) { _handlers.Add(handler); } internal static void RemoveHandler(IMessageHandler handler) { try { _handlers.Remove(handler); } catch (Exception ex) {} } internal static void Broadcast (string message) { foreach (IMessageHandler handler in _handlers) { handler.ReceiveMessage(message); } } }` 

主窗体实现了IMessageHandler接口,并在启动时将自身添加到Messenger作为处理程序。 任何需要向主窗体发送状态的进程只需要调用messenger的Broadcast方法。

我遇到的问题是,在后台进程完成之前,消息不会显示在表单上,​​并且UI也会被锁定。

处理接收消息的UI中的代码如下:

`

  public void ReceiveMessage(string message) { Dispatcher.Invoke(DispatcherPriority.Normal, new Action(AddText), message); } private void AddText(string text) { Label myLabel = new Label(); myLabel.Content = text; stackPanel1.Children.Add(myLabel); if (stackPanel1.Children.Count > 5) { stackPanel1.Children.RemoveAt(0); } }` 

为什么我的后台进程会冻结我的UI? 我该怎么做才能防止它? 为什么我的UI没有更新状态消息?

我有同样的问题, 这篇博文帮我解决了。

也许这是你的问题:

  Dispatcher.Invoke(DispatcherPriority.Normal, new Action(AddText), message); 

尝试将此更改为,

  Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(AddText), message); 

因为当您使用Invoke ,该方法将被执行并且应用程序等待它完成,但是使用BeginInvoke该方法被Asychnronously调用,并且应用程序继续执行,同时执行BeginInvoke引用的方法。

阅读: 是否使用Invoke或BeginInvoke

使用以下代码可以避免冻结UI。 在我的应用程序中,我使用了BackgroundWorker类。 通过使用代码更改表单上的任何内容,将引发运行时错误。

我使用下面的代码来避免这种情况,它对我来说非常适合。

 Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate() { rtf_status.AppendText("Validating XML against schema...Please wait\n"); })); 

请注意大括号之间的部分('{}’)如果您希望更改表单上的内容,则应放置代码。