如何使用来自后台线程的信息更新WPF窗口? [英] How do I update a WPF Window with information from a background thread?

查看:98
本文介绍了如何使用来自后台线程的信息更新WPF窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a wpf application which performs many tasks in the backgound, but still requires the UI to be responsive and to display the status of the various background tasks. It also has the option to not display the UI at all, in which case the status messages should be discarded without creating an instance of the main form at all.

我试图删除

StartupUri="MainWindow.xaml"

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

from App.xaml. Then, in App.xaml.cs, I have

`

    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.

    }`

这将显示主要形式(如有必要),并启动所有后台进程.这部分有效.

This shows the main form, if necessary, and starts all the background processes. This part works.

为了将消息从后台发送到UI,我实现了一个非常基本的Messenger:

In order to send messages from the background to the UI, I've implemented a very basic messenger:

`

internal interface IMessageHandler
{
    void ReceiveMessage(string message);
}

internal class Messenger
{
    private static List<IMessageHandler> _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方法.

The main form implements the IMessageHandler interface, and adds itself to the Messenger as a handler when it starts up. Any process that needs to send a status to the main form just needs to call the Broadcast method of the messenger.

我遇到的问题是,直到后台进程完成,消息才在表单上显示,并且直到那时UI都已锁定.

The problem I'm having, is that the messages are not being shown on the form until the background processes complete, and the UI is locked up until then as well.

UI中用于接收消息的代码如下:

The code in the UI which handles receiving messages is as follows:

`

    public void ReceiveMessage(string message)
    {
        Dispatcher.Invoke(DispatcherPriority.Normal,
                new Action<string>(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不使用状态消息进行更新?

Why are my background processes freezing my UI? What can I do to prevent it? And why is my UI not updating with the status messages?

推荐答案

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

Use the below code to avoid freezing the UI. In my application I have used a BackgroundWorker class. By changing anything on the form using code, a run time error is thrown.

我正在使用下面的代码来避免这种情况,它对我来说非常有效.

I am using the below code to avoid this and it works perfectly for me.

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

请注意括号之间的部分('{}'),如果要更改表单上的某些内容,应在此处放置代码.

Note the part after the between braces ('{}') this is where you should place your code if you wish to change something on the form.

这篇关于如何使用来自后台线程的信息更新WPF窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆