使用任务并行库更新进度条UI对象

4

基本上,我想在FormMain(WindowsForm)上更新ProgressBar UI对象。 我正在使用.NET 4.0

以下是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 ?
                    }
                 );
            }
        }
    }
}

你应该在 ProcessATask 内部更新进度条,否则它会立即填满。因为你使用独立任务来更新进度条。 - fofik
1
UpdateProgressBar在ProcessATask完成后执行。这是使用.ContinueWith定义的。我需要等待前一个任务完成,以便报告此任务已全部完成。 - hadi teo
2个回答

6
您可以使用 SynchronizationContext 来实现此功能。要将其用于 Task,您需要创建一个 TaskScheduler,可以通过调用 TaskScheduler.FromCurrentSynchronizationContext 来完成:
Task UpdateProgressBar = ProcessATask.ContinueWith(antecedent =>
    { 
        // you can update the progress bar object here
    }, TaskScheduler.FromCurrentSynchronizationContext());

这只有在您直接从UI线程调用Process()时才会起作用。

@MarkпјҢдҪ дёҚиғҪзӣҙжҺҘд»Һй—®йўҳдёӯзҡ„CustomProcessзұ»дҪҝз”ЁInvoke()пјҢеӣ дёәе®ғдёҚжҳҜдёҖдёӘControlгҖӮ - svick
我认为应该像这样使用 targetControl.Invoke(invokationDelegate);,利用目标控件的Invoke方法,这也是该方法存在的意义所在。难道我漏掉了什么吗? - 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);
                });
            }

        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接