2012-12-19 20 views
4

基本上我想更新FormMain(WindowsForm)上的ProgressBar UI对象。我使用.NET 4.0从任务并行库更新ProgressBar UI对象

以下是在Form1.designer.cs

namespace ProgressBarApp 
{ 
    public partial class Form1 : Form 
    {   
     private System.Windows.Forms.ProgressBar curProgressBar; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      CustomProcess theProcess = new CustomProcess(); 
      theProcess.Process(); 
     } 
    } 
} 

下面的代码是CustomProcess.cs的定义

namespace ProgressBarApp 
{ 
    class CustomProcess 
    { 
     public void Process() 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       Task ProcessATask = Task.Factory.StartNew(() => 
        { 
         Thread.Sleep(1000); // simulating a process 
        } 
       ); 

       Task UpdateProgressBar = ProcessATask.ContinueWith((antecedent) => 
        { 
         // how do i update the progress bar object at UI here ? 
        } 
       ); 
      } 
     } 
    } 
} 
+0

你应该更新内部ProcessATask进度,否则将立即填满。因为您使用独立的任务来更新进度条。 – fofik

+1

执行UpdateProgressBar完成ProcessATask之后。这是使用.ContinueWith定义的。我需要等到上一个任务完成,以便我可以报告此任务全部完成。 –

回答

6

您可以使用SynchronizationContext做到这一点。要使用它为Task,你需要创建一个TaskScheduler,您可以通过调用TaskScheduler.FromCurrentSynchronizationContext做:

Task UpdateProgressBar = ProcessATask.ContinueWith(antecedent => 
    { 
     // you can update the progress bar object here 
    }, TaskScheduler.FromCurrentSynchronizationContext()); 

仅当您直接从UI线程中调用Process()这将工作。

+0

或在UI线程中使用'Invoke' – Mark

+0

@Mark由于问题不是'Control',所以不能直接从'CustomProcess'类中使用'Invoke()'。 – svick

+0

我以为像targetControl.Invoke(invokationDelegate);',使用目标控件的Invoke-method,我认为这是该方法的全部要点。或者我在这里错过了什么? – Mark

4

如何使用System.Reactive.Linq

[更新]

using System.Reactive.Linq; 

namespace WindowsFormsApplication6 
{ 
    public partial class Form1 : Form 
    { 
     //private System.Windows.Forms.ProgressBar curProgressBar; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      CustomProcess theProcess = new CustomProcess(); 
      var x = Observable.FromEventPattern(theProcess, "TaskCompleted"); 
      curProgressBar.Maximum = 4; 
      x.Subscribe((a) => 
      { 
       curProgressBar.Value = ((CustomProcess)a.Sender).Counter; 
      }); 
      theProcess.Process(); 
     } 

    } 

    class CustomProcess 
    { 

     public int Counter { get; set; } 
     public event EventHandler TaskCompleted = OnTaskCompleted; 

     private static void OnTaskCompleted(object sender, EventArgs e) 
     { 
      ((CustomProcess)sender).Counter++; 
     } 
     public void Process() 
     { 

      for (int i = 0; i <= 3; i++) 
      { 
       Task ProcessATask = Task.Factory.StartNew(() => 
        { 
         Thread.Sleep(1000); // simulating a process 
        } 
       ); 
       var awaiter = ProcessATask.GetAwaiter(); 
       awaiter.OnCompleted(() => 
       { 
        TaskCompleted(this, null); 
       }); 
      } 

     } 
    } 
}