调度员.调用方法有时不工作

本文关键字:工作 调用 方法 调度员 | 更新日期: 2023-09-27 18:18:44

我在使用调度程序时遇到了一个非常奇怪的问题。在wpf中调用方法

背景:

我定义了一个用户控件,有一个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 . add方法运行,结果只是不出来。如果我改变Dispatcher。给调度员开发票。BeginInvoke,那么它是正常的。有人知道原因吗?

调度员.调用方法有时不工作

首先,你使用的BackgroundWorker是无效的,因为你试图在UI线程上运行DowWork方法,但该方法的整个目的是它在后台线程上运行。如果您想知道如何正确实现BackgroundWorker,那么请参阅我对如何正确实现具有ProgressBar更新的BackgroundWorker的回答?关于Stack Overflow的问题

然而,如果你只是想异步运行一些代码,你真的不需要使用BackgroundWorker这些天。相反,您可以使用Task类做这样的事情:

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类页面。从那一页:

为线程提供管理工作项队列的服务。

注意这里说的是一个线程,而不是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);
}