我使用Bindinglist<Object>
和DataGridView来填充对象列表并将其显示在DataGridView中。
我的列表是由另一个线程而不是DataGridView线程填充的,所以我在ListChanged()
方法中使用Invoke
方法,我在GUI线程中编写(DataGridView上的线程)。
现在,只要我在主线程中添加对象到BindingList(处理列表)- DataGridView被更新了Ok,但是,当我尝试在BindingList上运行Clear()
方法时-我的ListChanged()
方法运行,但是,我仍然得到异常:Cross-thread operation not valid: Control 'dgv' accessed from a thread other than the thread it was created on
。为什么会出现这个异常?我已经在ListChanged()
方法中处理GUI了,不是吗?
代码:
myBindingList.ListChanged += new ListChangedEventHandler(Events_ListChanged);
BindingSource source = new BindingSource(myBindingList, null);
dgv.DataSource = source;
在主线程中运行Clear()
方法:
myBindingList.Clear();
my ListChanged()
method:
void Events_ListChanged(object sender, ListChangedEventArgs e)
{
if (dgv.InvokeRequired)
{
dgv.Invoke(new UpdateDataGridItemDelegate(this.Events_ListChanged), sender, e);
return;
}
else
{
source.ResetBindings(false);
lblTotal.Text = myBindingList.Count.ToString();
}
}
我强调:当我将对象添加到绑定列表时,它工作得很好,并且我没有得到异常(我正在从我运行Clear()
方法的同一线程中执行),但是当我运行Clear()方法时,它会抛出我"交叉线程"异常。知道为什么吗?
我改变了我的ListChanged()
方法如下,它的工作原理!:
void Events_ListChanged(object sender, ListChangedEventArgs e)
{
if (dgv.InvokeRequired)
{
dgv.Invoke(new UpdateDataGridItemDelegate(this.Events_ListChanged), sender, e);
return;
}
else
{
if (e.ListChangedType == ListChangedType.Reset)
{
dgv.DataSource = null;
source = new BindingSource(myBindingList, null);
dgv.DataSource = source;
}
else
source.ResetBindings(false);
lblTotal.Text = myBindingList.Count.ToString();
}
}
我取消了DataGridView的数据源绑定,并在重置BindingList的情况下重新绑定到BindingList。