【问题标题】:How to display a loop's progress without pausing the loop?如何在不暂停循环的情况下显示循环的进度?
【发布时间】:2012-09-03 10:05:46
【问题描述】:

我有一个for 循环(在它自己的线程中运行),我正在计算循环的进度,并且我想在每次更改时显示进度值,但我想在外部运行消息显示命令循环,所以它不会暂停循环。

我已阅读How do I display progress during a busy loop?,但我不想使用后台工作者,因为我已经有一个使用启动循环的类的实例(即我不想嵌套后台工作者)。我假设替代方案是引发和监听事件,但我不确定在这种情况下如何实现。

那么,如何在不使用后台工作人员的情况下解决这个问题?

【问题讨论】:

  • 你用什么:winforms、wpf?
  • 我使用 Winforms。为什么这很重要?
  • 显示一些代码。与 GUI 解耦的 for 循环代码有多少?
  • stackoverflow.com/questions/4428817/… 只需使用 Dispatcher 设置 label.Text。

标签: c# for-loop backgroundworker progress


【解决方案1】:

如果是 Winforms,您只需使用匿名委托执行 MyForm.BeginInvoke() 即可更新进度显示。 BeginInvoke 是异步的,所以不会阻塞当前线程。

【讨论】:

    【解决方案2】:

    您需要在循环线程之外通知诸如 LoopWatcher 之类的东西。

    public class ProgressEventArgs : EventArgs
    {
        public int Number { get; private set; }
        public ProgressEventArgs(int num)
        {
            this.Number = num;
        }
    }
    
    public class Worker
    {
        public event EventHandler<ProgressEventArgs> ProgressChanged = delegate { };
    
        public void DoSomething()
        {
            for (int i = 0; i < 10; i++)
            {
                ProgressChanged(this, new ProgressEventArgs(i));
                Thread.Sleep(1000);   //just an example here
            }
        }
    }
    

    您可以在Worker.DoSomething 中看到,有一个循环需要花费时间。我在Worker中添加了一个事件,所以在课堂之外,订阅者可以知道进度发生了变化。

    var worker = new Worker();
    worker.ProgressChanged += (s, e) => Console.WriteLine(e.Number);
    Thread t = new Thread(worker.DoSomething);
    t.Start();
    

    【讨论】:

      【解决方案3】:

      由于提供的答案不符合我的要求,我对事件进行了一些研究,并按照我最初想要的方式解决了问题。

      我在开始循环的类中声明了一个事件:

      public delegate void ProgressChangedEvHandler(int progress);
      
      public event ProgressChangedEvHandler ProgressChanged;
      
      private void OnProgressChanged(int progress)
      {
          var handler = ProgressChanged;
          if (handler != null) handler(progress);
      }
      

      然后我从循环中调用事件:

      for (var index = 0; index < arrayListCount; index++)
      {
          var progress = (int) (100*(double) index/(double) arrayListCount);
          OnProgressChanged(progress);
      }
      

      然后我刚刚在不同的类中(在不同的线程上)创建了侦听器 (LoopClassInstance.ProgressChanged += LoopClassInstance_ProgressChanged;):

      private void LoopClassInstance_ProgressChanged(int progress)
      {
          toolStripProgressBar1.Value = progress;
      }
      

      【讨论】:

        猜你喜欢
        • 2022-12-10
        • 2012-03-01
        • 1970-01-01
        • 2017-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-10
        • 1970-01-01
        相关资源
        最近更新 更多