前段时间我使用基于WPF的UI编写了一个使用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;
}
}
然后完美的工作。但是现在我再次启动它并发现UI停止刷新,即LoadTextBlock不会消失,并且列表框中没有显示新闻。只有在我最小化应用程序后才会刷新。
我从DoWork中删除了所有解析功能,但效果相同。然后评论RunWorkerAsync并且UI开始正常工作。所以我建议问题是由BackgroundWorker引起的。但我无法理解它有什么问题?
由于
答案 0 :(得分:0)
我有点困惑的是没有抛出无效的跨线程错误(UnauthorizedAccessException),但是你可以使用一个扩展方法在目标控件的正确调度程序上调用你的UI Update逻辑。
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");
}
});
}