Как обновить окно WPF информацией из фонового потока? - PullRequest
0 голосов
/ 27 января 2011

Я создаю приложение wpf, которое выполняет много задач в фоновом режиме, но все же требует, чтобы пользовательский интерфейс реагировал и отображал состояние различных фоновых задач. Он также имеет возможность вообще не отображать пользовательский интерфейс, и в этом случае сообщения о состоянии должны быть отброшены без создания экземпляра основной формы.

Я пытался удалить

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.

    }`

Показывает основную форму, если необходимо, и запускает все фоновые процессы. Эта часть работает.

Чтобы отправлять сообщения из фона в пользовательский интерфейс, я реализовал очень простой мессенджер:

`

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 в качестве обработчика при запуске. Любой процесс, которому нужно отправить статус в основную форму, просто должен вызвать метод Broadcast мессенджера.

Проблема, с которой я столкнулся, заключается в том, что сообщения не отображаются в форме до тех пор, пока не завершатся фоновые процессы, и пользовательский интерфейс также будет заблокирован до тех пор.

Код в пользовательском интерфейсе, который обрабатывает получение сообщений, выглядит следующим образом:

`

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

Почему мои фоновые процессы замораживают мой интерфейс? Что я могу сделать, чтобы предотвратить это? И почему мой интерфейс не обновляется сообщениями о состоянии?

Ответы [ 3 ]

1 голос
/ 27 января 2011

У меня была та же проблема, и это сообщение в блоге помогло мне решить ее.

0 голосов
/ 27 января 2011

Используйте приведенный ниже код, чтобы избежать зависания пользовательского интерфейса.В моем приложении я использовал класс BackgroundWorker.Изменяя что-либо в форме с помощью кода, выдается ошибка времени выполнения.

Я использую приведенный ниже код, чтобы избежать этого, и он отлично работает для меня.

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

Обратите внимание на часть после скобок ('{}'), это то место, куда вы должны поместитьваш код, если вы хотите что-то изменить в форме.

0 голосов
/ 27 января 2011

Может быть, это ваша проблема:

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

Попробуйте изменить это на

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

Поскольку при использовании Invoke метод выполняется, и приложение ожидает его завершения, но при BeginInvoke метод вызывается асинхронно, и приложение продолжает выполняться, пока выполняется метод, указанный в BeginInvoke .

Прочитайте это: использовать ли Invoke или BeginInvoke

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...