在 WinForms 上使用 TPL 进行并行编程

a12*_*773 4 c# wpf winforms task-parallel-library

我尝试在 WinForms .NET 4.0 上使用 TPL,我按照适用于 WPF 的步骤(转到文章末尾)进行了一些小更改,以便它可以在 WinForms 上工作,但仍然不起作用。它应该显示结果在标签和 richTextBox 上,但它不是...我认为并行过程工作导致鼠标在我单击按钮时开始缓慢移动一段时间..

public static double SumRootN(int root)
{   double result = 0;
    for (int i = 1; i < 10000000; i++)
    {   result += Math.Exp(Math.Log(i) / root);}
    return result;
}
private void button1_Click(object sender, EventArgs e)
{   richTextBox1.Text = "";
    label1.Text = "Milliseconds: ";
    var watch = Stopwatch.StartNew();
    List<Task> tasks = new List<Task>();
    for (int i = 2; i < 20; i++)
    {   int j = i;
        var t = Task.Factory.StartNew
          (   () =>
                {   var result = SumRootN(j);
                    Dispatcher.CurrentDispatcher.BeginInvoke
                        (new Action
                             (   () => richTextBox1.Text += "root " + j.ToString() 
                                   + " " + result.ToString() + Environment.NewLine
                             )
                         , null
                        );
                 }
            );
        tasks.Add(t);
    }
    Task.Factory.ContinueWhenAll
         (  tasks.ToArray()
            , result =>
                {   var time = watch.ElapsedMilliseconds;
                    Dispatcher.CurrentDispatcher.BeginInvoke
                          (   new Action
                                (    () =>
                                      label1.Text += time.ToString()
                                 )
                           );
                }
        );
}
Run Code Online (Sandbox Code Playgroud)

Gen*_*нин 5

暂且不说这样做好不好,从学习的角度以及评论中提到的主题“System.Windows.Threading.Dispatcher 和 WinForms?” 答案有些令人困惑:

“如果您确定处于 UI 线程中(例如,在 Button.Click 处理程序中),Dispatcher.CurrentDispatcher 会为您提供 UI 线程调度程序,您可以像平常一样使用它从后台线程调度到 UI 线程”

值得一提的是(也提供了我对上述问题的 回答):

  • Task.Factory.StartNew()在不同于主 UI 或其子线程的多个线程上生成执行
  • 可以在任何线程上 使用Dispatcher
  • WPF 应用程序 OOTB(开箱即用)提供 System.Windows.Threading.Dispatcher DispatcherObject.DispatcherWinfows 表单中缺少的 UI 线程
  • 所讨论的问题Dispatcher.CurrentDispatcher是让调度程序由非 ui 线程的任务生成

无论如何,从对原始 WPF 代码进行最小更改的教学角度来看,您应该已经捕获并使用 UI 调度程序:

private void button1_Click(object sender, EventArgs e)
{   Dispatcher dispatcherUI = Dispatcher.CurrentDispatcher;//added **********
    richTextBox1.Text = "";
    label1.Text = "Milliseconds: ";
    var watch = Stopwatch.StartNew();
    List<Task> tasks = new List<Task>();
    for (int i = 2; i < 20; i++)
    {   int j = i;
        var t = Task.Factory.StartNew
          (   () =>
                {   var result = SumRootN(j);
      //Dispatcher.CurrentDispatcher.BeginInvoke//***changed to
                    dispatcherUI.BeginInvoke
                        (new Action
                             (   () => richTextBox1.Text += "root " + j.ToString() 
                                   + " " + result.ToString() + Environment.NewLine
                             )
                         , null
                        );
                 }
            );
        tasks.Add(t);
    }
    Task.Factory.ContinueWhenAll
         (  tasks.ToArray()
            , result =>
                {   var time = watch.ElapsedMilliseconds;
     //Dispatcher.CurrentDispatcher.BeginInvoke//**************changed to
                    dispatcherUI.BeginInvoke//added
                          (   new Action
                                (    () =>
                                      label1.Text += time.ToString()
                                 )
                           );
                }
        );
} 
Run Code Online (Sandbox Code Playgroud)