You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决使用Parallel.For搜索时dataGridView1跨线程访问错误

问题原因分析
  • 死锁根源:Parallel.For是同步阻塞方法,直接在UI线程的inputSearch_TextChanged事件中执行时,会阻塞当前UI线程等待所有并行任务完成,而并行任务里的Invoke又需要等待UI线程空闲才能执行,双方互相等待就形成死锁。
  • 未处理的跨线程访问:并行任务中直接读取inputSearch.Text属性,这也是跨线程访问UI控件的操作,同样会触发跨线程异常,原代码只处理了修改DataGridView的部分,漏了读取搜索框内容的操作。
  • 无效重复刷新:7个并行任务每个匹配到结果都会单独更新DataGridView数据源,不仅会导致多次无意义的UI刷新,还可能出现后执行的任务覆盖先执行任务结果的逻辑问题。
修复后的代码
private void inputSearch_TextChanged(object sender, EventArgs e)
{
    // 先在UI线程提前取好所有需要的参数,避免并行任务中跨线程访问控件
    string searchValue = inputSearch.Text.ToUpper();
    // 把并行逻辑扔到线程池执行,不阻塞UI线程
    Task.Run(() =>
    {
        List<DataRow> resultRows = new List<DataRow>();
        // 并行搜索所有列,把结果汇总
        Parallel.For(0, 7, i =>
        {
            var matched = dataTable.AsEnumerable()
                .Where(row => row[i].ToString().Contains(searchValue))
                .ToList();
            // 加锁避免多线程操作集合冲突
            lock (resultRows)
            {
                resultRows.AddRange(matched);
            }
        });
        // 统一更新UI
        Invoke(new Action(() =>
        {
            if (resultRows.Any())
            {
                // 去重避免同一条数据匹配多列重复显示
                dataGridView1.DataSource = resultRows.Distinct().CopyToDataTable();
                dataGridView1.Columns[7].Visible = false;
            }
            else
            {
                dataGridView1.DataSource = null;
            }
        }));
    });
}
额外优化建议
  • 如果输入频率很高,建议加防抖逻辑,比如用户停止输入300ms后再执行搜索,避免频繁触发并行搜索浪费资源。
  • DataTable本身不大的情况下,并行搜索的收益可能不如直接单线程遍历所有列,多线程上下文切换的开销可能超过并行收益,可以根据实际数据量测试调整。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:54:03