使用Control.Invoke()代替锁(Control)

时间:2011-09-28 17:25:42

标签: c# .net winforms multithreading locking

我正在研究一个多线程应用程序,它需要在进程中更新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()

(这是主要问题。当然,如果上述代码中有任何其他多线程错误,请发表评论)

1 个答案:

答案 0 :(得分:3)

有点多余,Invoke调用会将操作“调度”到UI线程。每个后续Invoke调用都将以串行方式调度,因此实际上不需要进行任何锁定。

您可以考虑使用BeginInvoke而不是Invoke命令来阻止工作线程阻塞,但同样,这将“串行”完成,因此无需担心锁定。