访问GUI元素没有按预期工作
本文关键字:工作 GUI 元素 访问 | 更新日期: 2023-09-27 17:50:02
当我运行下面的代码时,它应该用每个DataRow
的值填充ListBox
,但它正在用单个DataRow
的值填充ListBox
。
问题是什么,我该如何解决它?这是一个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());
}));
}
}
}
问题是您在匿名方法中捕获了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());
}));
}
或者更好的是,在后台线程中完成所有的数据访问:
foreach (DataRow drw in dtTemp.Rows)
{
string item = drw["Value"].ToString();
this.Dispatcher.BeginInvoke(new Action(delegate()
{
listBox1.Items.Add(item);
}));
}
注意,c# 5 只影响 还请注意,使用lambda表达式而不是匿名方法可以稍微缩短代码:foreach
循环,而不影响for
循环。foreach (DataRow drw in dtTemp.Rows)
{
string item = drw["Value"].ToString();
Action action = () => listBox1.Items.Add(item);
this.Dispatcher.BeginInvoke(action);
}
变量捕获再次发生。(Google:变量捕获)
尝试创建一个临时变量并将其传递给线程,像这样:void myThread()
{
using (DataTable dtTemp = DbConnection.db_Select_DataTable(srQuery))
{
foreach (DataRow drw in dtTemp.Rows)
{
DataRow tmp = drw;
this.Dispatcher.BeginInvoke(new Action(delegate()
{
listBox1.Items.Add(tmp["Value"].ToString());
}));
}
}
}