我有一个UserControl,其中包含一个名为mTreeView的TreeView控件。我可以从多个不同的线程获取数据更新,这些更新将导致TreeView被更新。为此,我设计了以下模式:所有数据更新事件处理程序必须获得锁并检查InvokeRequired;如果是,则通过调用Invoke来完成工作。下面是相关代码:
public partial class TreeViewControl : UserControl
{
object mLock = new object();
void LockAndInvoke(Control c, Action a)
{
lock (mLock)
{
if (c.InvokeRequired)
{
c.Invoke(a);
}
else
{
a();
}
}
}
public void DataChanged(object sender, NewDataEventArgs e)
{
LockAndInvoke(mTreeView, () =>
{
// get the data
mTreeView.BeginUpdate();
// perform update
mTreeView.EndUpdate();
});
}
}
我的问题是,在启动时,有时会在mTreeView.BeginUpdate()上出现InvalidOperationException,提示mTreeView正在从不同于创建它的线程更新。我回溯调用堆栈到我的LockAndInvoke,看到c.InvokeRequired是true,但else分支被执行了!就好像在else分支执行后,InvokeRequired在不同的线程上被设置为true一样。
我的方法是否有问题,我该如何防止这种情况发生?
编辑:我的同事告诉我,问题在于InvokeRequired在控件创建之前为false,因此这就是为什么它会在启动时出现的原因。他不确定该怎么办。有什么想法吗?