BackgroundWorker stops the WPF UI to be refreshed
Some time ago I wrote a simple application with the WPF-based UI that uses the 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;
}
}
It worked perfectly then. But now I have launched it again and found that the UI stops refreshing, i.e. LoadTextBlock doesn't disappear and news doesn't showed in the list box. It refreshes only after I minimize the app.
I removed all parsing functionality from the DoWork but got the sa开发者_如何学编程me effect. Then commented RunWorkerAsync and the UI started work normally. So I suggest the problem is caused by the BackgroundWorker. But I can't understand what is wrong with it?
Thanks
I am bit puzzled that no invalid-cross-thread error is thrown (UnauthorizedAccessException), but nonetheless you could use an extension method that calls your UI Update logic on the correct dispatcher for the target control.
public static class WindowExtensions
{
public static void Dispatch(this Control control, Action action)
{
if (control.Dispatcher.CheckAccess())
action();
else
control.Dispatcher.BeginInvoke(action);
}
}
Usage would be this in your case:
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");
}
});
}
精彩评论