我有一个 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 为真,但 else 分支被占用了!就好像在采用 else 分支之后,在不同的线程上将 InvokeRequired 设置为 true。
我的方法有什么问题吗?我能做些什么来防止这种情况发生?
编辑:我的同事告诉我,问题是在创建控件之前 InvokeRequired 为假,所以这就是它在启动时发生的原因。不过,他不确定该怎么做。有任何想法吗?