【问题标题】:WinForms DataGridView extended to be Multi-Threads safeWinForms DataGridView 扩展为多线程安全
【发布时间】:2022-01-09 08:08:35
【问题描述】:

亲爱的, 我正在研究多线程编程。我想将 DGV 扩展为多线程安全。代码似乎工作正常,但我不确定“锁定”语句的使用:

public class MultiThreadsDataGridView:DataGridView
{

    public void UpdateCell(int Row, int Column, string Value) {

        lock (this)
        {
            Invoke(
                new Action(
                    () => Rows[Row].Cells[Column].Value = Value
                    )
                );
        }
    }


    public void AddRow(params object[] value) {

        lock(this){
            Invoke(
                new Action(
                    () => Rows.Add(value)
                    )
                );
        }
    }

}

以这种方式使用的“锁”会按预期工作吗? 谢谢

【问题讨论】:

  • 这取决于您的期望。如果您希望只有一个线程可以在 AddRow 或 UpdateCell 中输入逻辑,那么可以。如果线程 A 开始调用 UpdateCell 并进入锁并且线程 B 想要 AddRow,线程 B 将在锁语句处等待/阻塞,至少直到线程 A 完成。
  • 我的问题是……为什么?因为windows控件只应该被创建它们的线程访问,这似乎没有意义
  • @rene 这就是锁定在那种情况下的工作方式,但是当从与处理 UI 的线程不同的线程调用时,Action 可能会失败。
  • @Cleptus 他们正在调用 Invoke,我认为这可以保证内部操作在 UI 线程上运行。这种情况发生了变化还是我在这里想念什么?
  • 每个线程更新它的行 - 每个线程都应该向 UI 线程发出信号,通知它是时候更新第 X 行了。只有一个线程(创建 DGV 的线程)应该是用于与之交互

标签: c# multithreading winforms


【解决方案1】:

一般来说,不允许使用其他线程访问 UI 元素。话虽如此,可以使用Control.Invoke 函数或BackgroundWorker 来完成。

您的代码确实可以按预期工作,但由于不必要的锁定而表现不佳。

查看官方文档了解更多信息How to make thread-safe calls to controls (Windows Forms .NET)

这是使用Control.Invoke() 的文档示例(我总是发现后台工作人员很头疼)。他们使用TextBox,应该与DataGridView相同

private void button1_Click(object sender, EventArgs e)
{
    var threadParameters = new System.Threading.ThreadStart(delegate { WriteTextSafe("This text was set safely."); });
    var thread2 = new System.Threading.Thread(threadParameters);
    thread2.Start();
}

public void WriteTextSafe(string text)
{
    if (textBox1.InvokeRequired)
    {
        // Call this same method but append THREAD2 to the text
        Action safeWrite = delegate { WriteTextSafe($"{text} (THREAD2)"); };
        textBox1.Invoke(safeWrite);
    }
    else
        textBox1.Text = text;
}

【讨论】:

  • OP 已经在调用 Invoke
  • @rene 是的,即使不需要它,这个代码示例也会表现得更好。如果您处于线程安全的场景中,那么以后不必要的锁定很可能会出现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-05
  • 2012-04-22
  • 2013-12-23
相关资源
最近更新 更多