使用IProgress <t> </t>从任务列表中的多个任务更新多个进度条

时间:2014-08-07 15:58:46

标签: c# asynchronous

我有多个并行运行的任务。它们被收集在一系列任务中。每个任务都有一个与之关联的进度条。我一直在尝试实现IProgress API,以便在任务运行时更新进度条。但是,进度条仅在任务完成时更新。

我有一组模拟我的问题的测试代码,无论我如何修改它,任务栏只在任务完成时更新。

在创建每个任务时,我传递将更新正确进度条的Progress对象。此Progress对象将传递给内部任务,以便使用每个循环进行更新。 Progress.Report()方法将检查InvokeRequired,尽管如果您使用IProgress API和异步方法,我认为这不应该是必要的。

我已经包含了代码。表单只有一个启动所有进程的按钮(button1),并且有11个进度条应该随每个任务更新。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }        

    private async void button1_Click(object sender, EventArgs e)
    {
        List<ProgressBar> listOfProgressBars = new List<ProgressBar>
            {
                progressBar1,
                progressBar2,
                progressBar3,
                progressBar4,
                progressBar5,
                progressBar6,
                progressBar7,
                progressBar8,
                progressBar9,
                progressBar10,
                progressBar11
            };

        List<Task<bool>> taskList = new List<Task<bool>>();
        foreach (ProgressBar pBar in listOfProgressBars)
        {
            pBar.Value = 0;
            pBar.Minimum = 0;
            pBar.Maximum = 100;
        }

        int i = 11;
        for (int j = 1; j <= i; j++)
        {
            ProgressBar thisProgressBar = listOfProgressBars[j - 1];
            var progress = new Progress<int>((int value) =>
            {
                UpdateProgressBar(thisProgressBar, value);
            });

            taskList.Add(InnerProcess(j, progress));
        }

        await Task.WhenAll(taskList);

    }

    public void UpdateProgressBar(ProgressBar pBar, int value)
    {
        if (this.InvokeRequired)
        {
            this.EndInvoke(this.BeginInvoke(new MethodInvoker(delegate() { UpdateProgressBar(pBar, value); })));
        }
        else
        {
            pBar.Value = value;
        }
    }

    public Task<bool> InnerProcess(int waitTime, IProgress<int> progress)
    {
        return Task<bool>.Run(() =>
            {
                var job = new LongJob();
                job.Delay(waitTime, progress);
                return true;
            });
    }

    class LongJob
    {
        public void Delay(int i, IProgress<int> progress)
        {
            for (int j = 1; j <= i; j++)
            {
                Thread.Sleep(500);
                if (progress != null)
                {
                    progress.Report(j/i*100);
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

progress.Report(j/i*100);

j/i是整数除法,因为j小于i直到完成,j/i为0。

将j转换为浮点数并且一切都很好

答案 1 :(得分:0)

由于整数除法,您的进度计算中存在错误。将其更改为:

progress.Report((int)(((double)j) / i * 100));