任务并行库+ winforms进度条

时间:2011-02-22 09:02:43

标签: winforms progress-bar task-parallel-library

我想使用来自任务的委托来更新winforms中的进度条。

 scheduler = TaskScheduler.FromCurrentSynchronizationContext();
        public delegate void NotifyAboutIterationEnd(int iteration);
        public event NotifyAboutIterationEnd Notify;
          var task = Task.Factory.StartNew(() =>
           {
        //...
                   Task.Factory.StartNew(() =>
                   {
                       Notify(++index);
               }, CancellationToken.None, TaskCreationOptions.None, scheduler);
    //...

当我启动这段代码时,我可以命中的最后一个断点符合Notify(++ index); 然后程序冻结,结束了。 如果我将调度程序更改为例如scheduler = TaskScheduler.Current;然后我有一个例外,gui无法从其他线程修改。这意味着委托/事件正常工作。那么为什么它不能在第一种情况下起作用呢?

2 个答案:

答案 0 :(得分:1)

这是因为Task.Factory.StartNew()实际上没有启动新任务,而是SCEDULE它。即使主要任务完成,默认的scheduller也可以启动它们。记住任务!=线程。 Thread.Start - allways立即启动线程,Task.Factory.StartNew或Task.Start只计划。您可以在Task.Factory.StartNew()之后使用.Wait()。这将导致等待进度条更新。 但是,我觉得这不是最佳解决方案。解决方案我真的建议如果你的计算花了很多时间我们Task.Factory.Startnew与TaskCreationOptions.LongRunning 和Notify.BeginInvoke用于更新进度条。必须根据Winforms Updating UI Asynchronously Pattern正确实现notify事件的处理程序。 你可以在Winforms Updating UI Asynchronously Pattern - Need to Generalize看一个例子 希望这有帮助!

平行缺乏;)。

答案 1 :(得分:0)

你可以这样做

         ProgressBar pb = new ProgressBar();   
         pb.Maximum = 100;   
         pb.Dock = DockStyle.Fill;   
         Controls.Add(pb); 

         int i = 0, flag = 5;
            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            Task.Factory.StartNew(() =>
            {
                while (i <= 100
                {
                    Task.Factory.StartNew(() =>
                    {
                        pb.Value++;
                    }, System.Threading.CancellationToken.None, TaskCreationOptions.None, uiScheduler);
                    System.Threading.Thread.SpinWait(50000000); // do work here   
            i++

                }
            });