报告进度不调用进度在 c# 中更改了任务

本文关键字:任务 调用 报告 | 更新日期: 2024-09-21 03:45:11

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {            
        int currentProgress=-1;
        while (currentProgress<length)
        {
            currentProgress=Worker.progress;
            backgroundWorker1.ReportProgress(currentProgress);
            Thread.Sleep(500);
            length = Worker.UrlList.Count;
        }
    }
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        int ix = e.ProgressPercentage;
        progressBar1.Value = ix;
        lblText.Text =ix+" %";
    }

我编写了一个程序,通过读取一个文件来下载页面源代码,其中包含大约 1000 个 URL。 所以我使用任务异步下载页面。 这里Worker.progress是当前执行的 URL 量。 尽管调试器命中backgroundWorker1.ReportProgress(currentProgress);但它永远不会进入backgroundWorker1_ProgressChanged

 private void StartButton_Click(object sender, EventArgs e)
    {            
        t.makeUrlList(inputFile);
        backgroundWorker1 = new BackgroundWorker();
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.DoWork += backgroundWorker1_DoWork;
        backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
        backgroundWorker1.RunWorkerAsync();
        t.RunTasks();
        Application.Exit();
    }

后台工作线程在启动按钮单击时初始化...

这是我的任务创建的地方。

public void RunTasks()
    {
        if (numOfTasks > UrlList.Count)
            numOfTasks=UrlList.Count-1;
       Task[] t = new Task[numOfTasks];
        int j = 0;
        while ( j < UrlList.Count-1)
        {
           for (int i = 0; (i < t.Count())&&(j<UrlList.Count-1); i++)
            {

                try
                {
                    if (t[i].IsCompleted || t[i].IsCanceled || t[i].IsFaulted)
                    {
                        t[i] = Task.Run(() => FindWIN(j));
                        j++;
                        progress = j;                            
                    }
                }
                catch (NullReferenceException ex)
                {
                    t[i] = Task.Run(() => FindWIN(j));
                    j++;
                    progress = j;
                }
                }
            }
        }

报告进度不调用进度在 c# 中更改了任务

如果要 BackgroundWorker 支持更新进度信息,则 WorkerReportsProgress 的值应设置为 true 。如果此属性为 true,则用户代码可以调用 ReportProgress 来启动事件 ProgressChanged 。

后台工作线程初始化:-

 backgroundWorker1 = new BackgroundWorker();
 backgroundWorker1.WorkerReportsProgress = true;
 backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
 backgroundWorker1.ProgressChanged+=backgroundWorker1_ProgressChanged;
 backgroundWorker1.RunWorkerAsync();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
            int currentProgress = -1;
            decimal length=1000;
            while (currentProgress < length)
            {
                currentProgress = Worker.progress;
                backgroundWorker1.ReportProgress(currentProgress);
                Thread.Sleep(500);
                length = Worker.UrlList.Count;
            }
 }
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)        {
            int ix = e.ProgressPercentage;
            progressBar1.Value = ix;
            lblText.Text = ix + " %";
}

您应该在初始化阶段将 worker 的 WorkerReportsProgress 属性设置为 true。

请参阅下面的演示代码。这大多未经测试,当然也不是"生产标准",但它应该给你一个良好的开端!

  1. 它使用ConcurrentQueue来保存要处理的 URL 列表。这是线程安全的,使生活更轻松。

  2. 它具有可配置数量的 url 和任务。最好不要创建 1000 个任务,而是有一个工作项队列和一个较小的任务池,这些任务池将项目从队列中"拉出",直到它为空。这意味着您可以对不同数量的任务进行性能测试,并为您的问题找到最佳值。

  3. 它在更新进度条时使用 Invoke - 这避免了跨线程异常。

  4. 没有BackgroundWorker - 只有TaskFactoryTask

    public partial class Form1 : Form
    {
        private const int UrlCount = 1000;
        private const int taskCount = 10;
        private ConcurrentQueue<string> urlList;
        private List<Task> taskList;
        public Form1()
        {
            InitializeComponent();
        }
        private void ResetQueue()
        {
            // fake up a number of strings to process
            urlList = new ConcurrentQueue<string>(Enumerable.Range(0, UrlCount)
                      .Select(i => "http://www." + Guid.NewGuid().ToString() + ".com"));
        }
        private void button1_Click(object sender, EventArgs e)
        {
            ResetQueue();
            var taskFactory = new TaskFactory();
            // start a bunch of tasks
            taskList = Enumerable.Range(0, taskCount).Select(i => taskFactory.StartNew(() => ProcessUrl()))
                                  .ToList();
        }
        void ProcessUrl()
        {
            string current;
            // keep grabbing items till the queue is empty
            while (urlList.TryDequeue(out current))
            {
                // run your code
                FindWIN(current);
                // invoke here to avoid cross thread issues
                Invoke((Action)(() => UpdateProgress()));
            }
        }
        void FindWIN(string url)
        {
            // your code here
            // as a demo, sleep a sort-of-random time between 0 and 100 ms
            Thread.Sleep(Math.Abs(url.GetHashCode()) % 100);
        }
        void UpdateProgress()
        {
            // work out what percentage of the queue is processed
            progressBar1.Value = (int)(100 - ((double)urlList.Count * 100.0 / UrlCount));
        }
    }