繁体   English   中英

C#4.0从Parallel.ForEach中访问表单控件

[英]C# 4.0 Accessing form control from within Parallel.ForEach

下面的代码运行正常。 我想知道它是否真的正确?

if (openFileDialog.ShowDialog() == DialogResult.OK)
{
    Parallel.ForEach(openFileDialog.FileNames, currentFile =>
    {
       try
       {
           StreamReader FileReader = new StreamReader(currentFile);
           do
           {
               URLtextBox.Invoke(new MethodInvoker(delegate
               {
                   URLtextBox.Text += SelectURLfromString(FileReader.ReadLine());
               }));
           }
           while (FileReader.Peek() != -1);
           FileReader.Close();
        }
        catch (System.Security.SecurityException ex)
        {
            ...
        }
        catch (Exception ex)
        {
            ...
        }
     });
}

否则我得到“跨线程操作无效。控制'URLtextBox'从另一个线程访问”或卡住应用程序。

代码是正确的 - 您需要使用Invoke从GUI线程外部刷新控件。 但是,您正在SelectURLfromString(FileReader.ReadLine()); 在GUI线程中的方法,你应该替换它

   string url = SelectURLfromString(FileReader.ReadLine());
   URLtextBox.Invoke(new MethodInvoker(delegate
   {
       URLtextBox.Text += url;
   }));

尽量减少GUI线程中的工作。

除非您编组到UI线程,否则无法安全地更新工作线程的UI控件。

看一下TaskScheduler.FromCurrentSynchronizationContext

如何:在指定的同步上下文上安排工作

代码是正确的,您需要Invoke以便在GUI线程中更新控件。

但是,还有一些其他的东西在代码中没有意义:

  • 您正在执行使用非并行资源的并行操作。 你的线程将争夺磁盘的注意力,因为它的速度相对较低,显然是瓶颈。

  • 您将从多个文件中读取行,并将它们混合在一个文本框中。 在这种特定情况下,这可能是正常的,但通常会产生不可预测的结果。

  • 您正在使用+=操作来连接字符串,这种方法因其糟糕的可伸缩性而臭名昭着。 在这种情况下,这可能不是一个大问题,因为磁盘瓶颈可能要糟糕得多。

Invoke是必需的,因为控件绑定到创建其关联User32窗口(通常称为HWND )的线程。 也就是说,您可以通过在Invoke的委托之外读取和处理文件的内容来优化一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM