当我在wpf中使用dispatcher.invoke方法时,我遇到了一个非常奇怪的问题。
背景:
我定义了一个用户控件,有一个DoWorkEventArgs支持一些异步工作:
public class MyUserControl : UserControl
{
private BackgroundWorker bw;
public MyUserControl()
{
bw.DoWork += new DoWorkEventHandler(DoWorkMethod);
}
public void StartWork()
{
bw.RunWorkerAsync();
}
void DoWorkMethod(object sender, DoWorkEventArgs e)
{
this.Dispatcher.Invoke((System.Action)delegate()
{
//Add some item in a ListBox, this ListBox is defined in the user control.
TextBlock b = new TextBlock();
//some code
Listbox.Items.Add(b);
}
}
}
单击按钮时,我创建了此用户控件的2个实例并调用StartWork方法:
MyUserControl control1 = new MyUserControl();
MyUserControl control2 = new MyUserControl();
control1.StartWork();
control2.StartWork();
这是问题,有时候usercontrol1中的ListBox没有更新,其中没有项目,有时这种情况发生在usercontrol2的ListBox中,我调试它们,我发现代码运行正常,ListBox.Items。添加方法运行,结果不会出来。 如果我将Dispatcher.Invoie更改为Dispatcher.BeginInvoke,那么它是正常的。 有人知道原因吗?
答案 0 :(得分:0)
首先,您对BackgroundWorker
的使用无效,因为您尝试在UI线程上运行DowWork
方法,但该方法的全部目的是它在后台线程上运行。如果您想知道如何正确实现BackgroundWorker
,请在Stack Overflow上查看我对How to correctly implement a BackgroundWorker with ProgressBar updates?问题的回答。
但是,如果您只是想异步运行某些代码,那么这些天你真的不需要使用BackgroundWorker
。相反,您可以使用Task
class执行以下操作:
Task.Factory.StartNew(() => NameOfMethodToRunAsynchronously);
如果您需要在UI线程上运行部分NameOfMethodToRunAsynchronously
方法,那么您可以返回Dispatcher.Invoke
来电:
private void NameOfMethodToRunAsynchronously()
{
// Some long running process
Dispatcher.Invoke((System.Action)delegate()
{
//Add some item in a ListBox, this ListBox is defined in the user control.
TextBlock b = new TextBlock();
//some code
Listbox.Items.Add(b);
}
}
最后,要回答您对Dispatcher
课程的原始问题,请参阅MSDN上的Dispatcher
Class页面。从该页面:
提供管理线程工作项队列的服务。
请注意,它表示一个线程而不是 UI线程。这意味着可以成为您想要的UI线程,但不一定如此。为了确保它将用于UI线程,我们可以简单地在MainWindow.xaml.cs
的构造函数中的UI线程上设置它:
Dispatcher uiDispatcher = Application.CurrentDispatcher;
因此,为了确保您的Dispatcher
能够在UI线程上运行,只需使用该实例:
uiDispatcher.Invoke((System.Action)delegate()
{
//Add some item in a ListBox, this ListBox is defined in the user control.
TextBlock b = new TextBlock();
//some code
Listbox.Items.Add(b);
}