首页 > 解决方案 > 如何从 Parallel.ForEach 循环访问 winform 文本框?

问题描述

我正在处理 C# 中的文本文件列表。由于性能原因,我为此使用了 Parallel.ForEach。我需要richTextBox1在我的表单上写信,正在处理哪个文件。

由于我无法从 Parallel.ForEach 的不同线程访问表单,因此我WriteToBox使用 Invoke 创建了该方法。

public partial class Form2 : Form
{
    private static Form2 frmReference;
    private delegate void SafeCallDelegate(string text)
    public Form2()
    {
        InitializeComponent();
        frmReference = this;
    }
    public Dictionary<string, HashSet<string>> FindStrings(List<string> rccFiles)
    {
        Dictionary<string, HashSet<string>> sensitiveData = new Dictionary<string, HashSet<string>>();

        Parallel.ForEach(rccFiles, rccFile =>
        {
            //write which file is beeing processed
            WriteToBox("Searching in: " + rccFile);

           //some code
        });

        return sensitiveData;
    }

    public void WriteToBox(string text)
    {
        if (frmReference.richTextBox1.InvokeRequired)
        {
            var d = new SafeCallDelegate(WriteToBox);
            Invoke(d, new object[] { text });
        }
        else
        {
            frmReference.richTextBox1.AppendText("\r\n" + text);
            frmReference.richTextBox1.Update();
            frmReference.richTextBox1.ScrollToCaret();
        }
    }
}

当我运行程序时,它只会写入第一个处理的文件并且表单冻结(死锁?)。您知道如何从并行循环写入文本框吗?感谢您的任何建议!问候,马丁

标签: c#winforms

解决方案


Parallel.ForEach(在 UI 线程上运行)正在等待所有任务完成,WriteToBox 也是如此,因为它想要Invoke. 这些线程然后进入死锁。最简单的修复方法是替换InvokeBeginInvoke.

Anothey 方法是将 Parallel.ForEach 代码包装到单独的线程(非 UI)中,因为不需要此代码在 UI 上运行。

Task.Run(Parallel.ForEach(rccFiles, rccFile =>
{
    //write which file is beeing processed
    WriteToBox("Searching in: " + rccFile);

    //some code
}));

推荐阅读