我正在研究一个多线程应用程序,它需要在进程中更新Winforms控件(A DataGridView)。为了防止多次访问同一个共享资源,我开始使用以下锁结构:
if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
while (DGV.Columns.Count < DesiredColumnCount)
{
DGV.Columns.Add(newColumn);
}
}
然后我意识到,由于DGV是在UI线程上创建的,因此需要.Invoke()
'd。这会将代码更改为:
if (DGV.Columns.Count >= DesiredColumnCount) return;
lock(DGV)
{
DGV.Invoke(new MethodInvoker(() =>
{
while (DGV.Columns.Count < DesiredColumnCount)
{
DGV.Columns.Add(newColumn);
}
}
}
我的问题是:这不是多余的吗? lock
将阻止工作线程,直到它具有对DGV
的独占访问权限,Invoke()
将阻止工作线程,直到UI线程可以获取调用请求并执行代码。我不能只使用Invoke()
?
(这是主要问题。当然,如果上述代码中有任何其他多线程错误,请发表评论)
答案 0 :(得分:3)
有点多余,Invoke
调用会将操作“调度”到UI线程。每个后续Invoke
调用都将以串行方式调度,因此实际上不需要进行任何锁定。
您可以考虑使用BeginInvoke
而不是Invoke
命令来阻止工作线程阻塞,但同样,这将“串行”完成,因此无需担心锁定。