如何修复错误:从不同的线程访问了“dataGridView1”控件[重复]

Posted

技术标签:

【中文标题】如何修复错误:从不同的线程访问了“dataGridView1”控件[重复]【英文标题】:How to fix the error: the 'dataGridView1' control was accessed from a different thread [duplicate] 【发布时间】:2021-10-04 10:16:41 【问题描述】:

大家早上好,我在重写 DataGrid 时遇到了麻烦,该函数可以工作,但我需要进行更快的搜索,所以我的想法是添加并行性。

但在应用后者时,它会为我生成一个错误:System.InvalidOperationException:'无效的跨线程操作:控件'dataGridView1'是从与执行创建的线程不同的线程访问的。'

问题对我来说很清楚,但是我不知道如何解决它。各位大神能帮帮我吗?

我已经尝试过调用 Invoke,但程序进入了无限循环。

private void inputSearch_TextChanged(object sender, EventArgs e)
    
        Parallel.For(0, 7, i =>
        
            Ricerca(i);
        );
    

private void Ricerca(int i)
    
        string searchValue = inputSearch.Text.ToUpper();
  
        var re = from row in dataTable.AsEnumerable()
                 where
                 row[i].ToString().Contains(searchValue)
                 select row;
        if (re.Count() != 0)
        
            Invoke(new Action(() =>
            
                dataGridView1.DataSource = re.CopyToDataTable();
                dataGridView1.Columns[7].Visible = false;
            ));

            
        
    

【问题讨论】:

不要直接从另一个线程访问DataGrid。仅从您的 UI 线程访问您的 UI。如果您有要并行执行的计算,请将其结果存储在其他地方并使用 UI 线程读取这些结果,并在您的工作人员完成后将它们应用到 UI。还有一些方法可以将部分执行“委托”到 UI 线程中,但这有一些警告,请查看SynchronizationContext(更深入的here)。 无限循环与第一个问题有什么关系吗?看起来您使用调用解决了一个问题,现在您遇到了第二个问题。 【参考方案1】:

您遇到了死锁,因为您在 inputSearch_TextChanged 方法(由 UI 线程调用)中阻塞了 UI 线程。

如果您的意图是并行化 Linq 表达式,请将 Ricerca 方法一分为二。该方法的最后一部分应该在并行之外调用,可能直接在inputSearch_TextChanged 上调用。

更好的解决方案可能是改用 .NET Task。

否则,如果你根本不需要并行,你可以用一个简单的for替换它。

【讨论】:

【参考方案2】:

我能够按照 Cherry 的建议通过将内容保存在另一个表中并稍后重新复制来解决问题。

private void inputSearch_TextChanged(object sender, EventArgs e)
    
        Parallel.For(0, 7, i =>
        
            Ricerca(i);
        );
        dataGridView1.DataSource = table;
        dataGridView1.Columns[7].Visible = false;
    

    private void Ricerca(int i)
    
        string searchValue = inputSearch.Text.ToUpper();

        var re = from row in dataTable.AsEnumerable()
                 where
                 row[i].ToString().Contains(searchValue)
                 select row;
        if (re.Count() != 0)
        
            table = re.CopyToDataTable();
        
    

谢谢大家!

【讨论】:

以上是关于如何修复错误:从不同的线程访问了“dataGridView1”控件[重复]的主要内容,如果未能解决你的问题,请参考以下文章

“调用线程无法访问此对象,因为不同的线程拥有它”从 WPF 中的不同线程更新 UI 控件时出现错误

如何修复“线程 1:致命错误:在展开可选值时意外发现 nil”错误? [复制]

如何修复访问被拒绝路径错误asp.net应用程序访问网络共享

LUMEN:如何修复 SQLSTATE [42000]:语法错误或访问冲突:laravel 流明上的 1071

如何从不同的线程访问对象而不会发生冲突?

如何从不同的线程访问 MainThread 元素? [复制]