BackgroundWorker останавливает обновление пользовательского интерфейса WPF - PullRequest
1 голос
/ 25 июля 2011

Некоторое время назад я написал простое приложение с пользовательским интерфейсом на основе WPF, которое использует BackgroundWorker:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.RunWorkerAsync();
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        LoadTextBlock.Visibility = Visibility.Hidden;
        if (e.Error == null)
        {
            foreach (TechNews news in (e.Result as List<TechNews>))
            {
                NewsListBox.Items.Add(news);
            }
        }
        else
        {
            MessageBox.Show(e.Error.Message, "Error");
        }
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        CNetTechNewsParser parser = new CNetTechNewsParser();
        parser.Parse();
        e.Result = parser.News;
    }
}

Тогда оно работало идеально.Но теперь я запустил его снова и обнаружил, что пользовательский интерфейс перестает обновляться, то есть LoadTextBlock не исчезает и новости не отображаются в списке.Он обновляется только после того, как я свернул приложение.

Я удалил все функции синтаксического анализа из DoWork, но получил тот же эффект.Затем прокомментировал RunWorkerAsync и пользовательский интерфейс начал работать нормально.Поэтому я полагаю, что проблема вызвана BackgroundWorker.Но я не могу понять, что с ним не так?

Спасибо

1 Ответ

0 голосов
/ 25 июля 2011

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

public static class WindowExtensions
{
        public static void Dispatch(this Control control, Action action)
        {
            if (control.Dispatcher.CheckAccess())
                action();
            else
                control.Dispatcher.BeginInvoke(action);
        }
}

Использование будет в вашем случае:

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    this.Dispatch(() =>
    {
        LoadTextBlock.Visibility = Visibility.Hidden;
        if (e.Error == null)
        {
            foreach (TechNews news in (e.Result as List<TechNews>))
            {
                NewsListBox.Items.Add(news);
            }
        }
        else
        {
            MessageBox.Show(e.Error.Message, "Error");
        }
    });
}
...