后台工作者对UI的访问问题

问题描述

| 我正在将项目从Winforms转移到WPF。当我的代码基于WinForms时,我使用了(this.Invokerequired)检查线程是否具有访问权限。现在,根据我的Mainform使用以下代码
    // this is the delegate declaration to Allow Background worker thread to write to Log Output
    delegate void LogUpdateCallBack(String LogMessage);

    // method to update the Log Window from the Background Thread
    public void LogUpdate(String LogMessage)
    {
        Console.WriteLine(\"Entering\");
        if (!Application.Current.dispatcher.CheckAccess())
        {
            Console.WriteLine(\"Thread doesn\'t have UI access\");
            LogUpdateCallBack callback = new LogUpdateCallBack(LogUpdate);
            Application.Current.dispatcher.Invoke(callback,LogMessage);
        }
        else
        {
            Console.WriteLine(\"Thread has UI access\");
            listBox_Output.Items.Add(LogMessage);
            Console.WriteLine(LogMessage);
            // listBox_Output.TopIndex = listBox_Output.Items.Count - 1;
        }
        Console.WriteLine(\"Exiting\");
    }
我的问题是列表框未更新。没有错误或异常,我已经尝试更新其他UI控件。 LogMessage正在写入“输出”窗口,所以我很困惑。 这是示例控制台输出
Entering
Thread doesn\'t have UI access
Entering
Thread has UI access
My LogMessage is output here 
Exiting
Exiting
Entering
Thread doesn\'t have UI access
Entering
Thread has UI access
My LogMessage is output here 
Exiting
Exiting
我已经尝试过更新其他UI控件,只是为了检查列表框是否存在问题,但是没有运气。 除了切换到CheckAccess()之外,我在新WPF代码中所做的唯一其他主要更改是将在Background worker中运行的所有代码都基于另一个Class ..我不确定这是否可以作为一部分问题? - @乔·雷诺 我尝试了你的想法:
Application.Current.dispatcher.BeginInvoke(new LogUpdateCallBack(LogUpdate),LogMessage)
但是,如果我输出,我的列表框仍然没有更新
Console.WriteLine(listBox_Output);
我看到列表框数组不断增长:
System.Windows.Controls.ListBox Items.Count:2020
System.Windows.Controls.ListBox Items.Count:2021
System.Windows.Controls.ListBox Items.Count:2022
System.Windows.Controls.ListBox Items.Count:2023
System.Windows.Controls.ListBox Items.Count:2024
System.Windows.Controls.ListBox Items.Count:2025
但是形式没有变化。这非常令人困惑!     

解决方法

        我也刚开始使用WPF,不得不从旧的WinForms方法中重新学习。我一直在使用BeginInvoke()和我的屏幕(窗体)上的这种语法...
public delegate void WorkCompleted();

        /// <summary>
        /// Marks the end of the progress
        /// </summary>
        private void ProgressComplete()
        {
            if (!this.Dispatcher.CheckAccess())
            {
                this.Dispatcher.BeginInvoke(new WorkCompleted(ProgressComplete),System.Windows.Threading.DispatcherPriority.Normal,null);
            }
            else
            {
                this.buttonClose.Visibility = Visibility.Visible;
                this.progressBarStatus.IsIndeterminate = false;
            }
        }
    ,        我终于解决了。 我的问题是,当我从另一个线程和另一个类调用LogUpdate方法时,因此我需要将对包含列表框的主窗体的引用传递给此类,而不是在辅助窗体中创建主窗体的新实例。类。 所以不要在我的第二堂课中有这个声明:
public MainWindow MainForm = new MainWindow();
我需要将表单的引用传递到辅助类的方法中:
    public void Plot(BackgroundWorker worker,MainWindow MainForm)
    ,        在WPF中,所有UI控件都派生自DispatcherObject。这意味着您的ListBox控件本身就是一个可调度的对象。尝试在该对象上调用Dispatcher,而不是依赖表单本身。取出委托上的参数(因为无论如何您都可以访问LogMessage变量),它看起来像:
public void LogUpdate(string LogMessage)
{
    Console.WriteLine(\"Entering\");
    if (listBox_Output.Dispatcher.CheckAccess())
    {
        listBox_Output.Dispatcher.Invoke(new LogUpdateCallBack(delegate
        {
            listBox_Output.Items.Add(LogMessage);
        }));
        Console.WriteLine(LogMessage);
    }
}
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...