访问GUI元素无法按预期工作

Mon*_*RPG 1 c# wpf user-interface multithreading task

当我运行下面的代码时,它应该填充ListBox每个DataRow值,但它填充ListBoxDataRow值.

有什么问题,如何解决?这是一个C#4.0 WPF应用程序.

    Task.Factory.StartNew(() =>
    {
        myThread();
    });

void myThread()
{
    using (DataTable dtTemp = DbConnection.db_Select_DataTable(srQuery))
    {
        foreach (DataRow drw in dtTemp.Rows)
        {   
            this.Dispatcher.BeginInvoke(new Action(delegate()
            {
                listBox1.Items.Add(drw["Value"].ToString());
            }));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

问题是你drw在匿名方法中捕获变量.该变量正在foreach循环中更新,因此,当您在调度程序线程上调用委托时,每次都会获得相同的值.在C#5中,这是可以的(这是一个常见的错误,语言已经改变以避免它)但在C#5之前,你需要在循环中复制变量:

foreach (DataRow drw in dtTemp.Rows)
{   
    DataRow copy = drw;
    this.Dispatcher.BeginInvoke(new Action(delegate()
    {
        listBox1.Items.Add(copy["Value"].ToString());
    }));
}
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,在后台线程中进行所有数据访问:

foreach (DataRow drw in dtTemp.Rows)
{   
    string item = drw["Value"].ToString();
    this.Dispatcher.BeginInvoke(new Action(delegate()
    {
        listBox1.Items.Add(item);
    }));
}
Run Code Online (Sandbox Code Playgroud)

请注意,对C#5的更改影响foreach- 而不是for循环.

另请注意,使用lambda表达式而不是匿名方法可以略微缩短代码:

foreach (DataRow drw in dtTemp.Rows)
{   
    string item = drw["Value"].ToString();
    Action action = () => listBox1.Items.Add(item);
    this.Dispatcher.BeginInvoke(action);
}
Run Code Online (Sandbox Code Playgroud)