C# BackgroundWorker停止要刷新的WPF UI
不久前,我使用基于WPF的UI编写了一个简单的应用程序,它使用BackgroundWorker:C# BackgroundWorker停止要刷新的WPF UI,c#,.net,wpf,backgroundworker,C#,.net,Wpf,Backgroundworker,不久前,我使用基于WPF的UI编写了一个简单的应用程序,它使用BackgroundWorker: public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { BackgroundW
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;
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
已加载私有无效窗口(对象发送器、路由目标)
{
BackgroundWorker工人=新的BackgroundWorker();
worker.DoWork+=新的doworkereventhandler(worker\u DoWork);
worker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(worker\u RunWorkerCompleted);
worker.RunWorkerAsync();
}
私有void worker\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
LoadTextBlock.Visibility=可见性.Hidden;
如果(e.Error==null)
{
foreach(TechNews中的新闻(例如,结果作为列表))
{
NewsListBox.Items.Add(新闻);
}
}
其他的
{
MessageBox.Show(例如Error.Message,“Error”);
}
}
私有void worker_DoWork(对象发送方,DoWorkEventArgs e)
{
CNetTechNewsParser=新的CNetTechNewsParser();
parser.Parse();
e、 结果=parser.News;
}
}
当时它工作得很好。但现在我再次启动它,发现UI停止刷新,即LoadTextBlock不会消失,列表框中也不会显示新闻。只有在我最小化应用程序后,它才会刷新
我从DoWork中删除了所有解析功能,但得到了相同的效果。然后注释RunWorkerAsync,UI开始正常工作。所以我认为问题是由幕后工作人员造成的。但我不明白这是怎么回事
感谢我有点困惑,没有抛出无效的跨线程错误(UnauthorizedAccessException),但是您可以使用扩展方法,在目标控件的正确调度程序上调用UI更新逻辑
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");
}
});
}
private void worker\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
此。分派(()=>
{
LoadTextBlock.Visibility=可见性.Hidden;
如果(e.Error==null)
{
foreach(TechNews中的新闻(例如,结果作为列表))
{
NewsListBox.Items.Add(新闻);
}
}
其他的
{
MessageBox.Show(例如Error.Message,“Error”);
}
});
}
worker\u RunWorkerCompleted函数的线程上下文是什么?此函数可能执行不正确的跨线程操作。尝试Dispatcher.BeginInvoke进行UI更新,而不是直接控制访问。@AlexFarber尝试了Dispatcher.Invoke,但之前没有成功。现在试一下你的变体,瞧,它起作用了!但更有趣的是,我再次尝试了直接访问——现在它也能工作了!那很神秘。。。无论如何,谢谢你的回答,问题看起来已经解决了。据我所知,RunWorkerCompleted事件处理程序是由创建BackgroundWorker的线程运行的,在我的例子中是UI线程,因此不需要跨线程操作。后台线程运行DoWork事件处理程序,创建控件的线程运行ProgressChanged和RunWorkerCompleted事件处理程序