2010-09-16 104 views
3

在C#,windows窗体中创建.net应用程序。如何在100循环循环的每个循环中更新进度条1步? (我正在处理循环中的Excel工作表。) 进度条控件位于UI类中,它连接到连接到自定义类 (MVC模式)的控制器类。循环在自定义类中。 我是否需要在每种方法中一直发送UI类实例还是有更好的方法?如何在每个循环周期内一步更新进度条? C#

当前进度条在循环结束后更新。 Application.doevents和.update或.refresh不起作用。

+2

在较低级别的活动发布广告进展情况时出现了什么问题? – Joey 2010-09-16 13:38:58

+0

对不起,我不明白你刚刚说的。进度条被定义在一个更高的类中,如果我更新低级类的值,上层类将如何知道?我不得不将ui类实例或进度条实例传递到较低级别。 – 2010-09-16 13:45:46

+0

我不确定,但如果更新发生延迟,它几乎听起来像是一个线程问题。你在使用invoke吗(如果有必要)? – 2010-09-16 13:49:19

回答

5

说下面是你的类负责做循环工作。添加一个事件来指示你的进度。然后从你的用户界面简单地处理该事件并相应地更新进度条。

sealed class Looper 
{ 
    public event EventHandler ProgressUpdated; 

    private int _progress; 
    public int Progress 
    { 
     get { return _progress; } 
     private set 
     { 
      _progress = value; 
      OnProgressUpdated(); 
     } 
    } 

    public void DoLoop() 
    { 
     _progress = 0; 
     for (int i = 0; i < 100; ++i) 
     { 
      Thread.Sleep(100); 
      Progress = i; 
     } 
    } 

    private void OnProgressUpdated() 
    { 
     EventHandler handler = ProgressUpdated; 
     if (handler != null) 
     { 
      handler(this, EventArgs.Empty); 
     } 
    } 
} 

你可能会被具有BackgroundWorker为你的用户界面,其中在backgroundWorker.DoWork事件调用looper.DoLoop()的一部分实现这一点。然后在looper.ProgressUpdated事件的处理程序中,您可以调用backgroundWorker.ReportProgress来从UI线程增加进度条。

请注意,在您的ProgressUpdated事件所携带的信息中包含进度本身可能更有意义(我只是不想写出来自EventArgs的新类来说明这一点;您可能会得到图片无论如何)。

另请注意,除非您正在使用UI线程的单独线程上的循环执行代码,否则上述内容确实没有任何意义。否则,无论如何,所有工作都会在下一次UI刷新前完成,因此您的进度条不会提供任何值(当循环完成时,它只会从0到100)。

只是一个例子,可以实现这种事情。

+0

什么叫你在哪里有控制私有变量的公共结构?那是封装吗? – 2010-09-16 14:36:30

+0

@hi科技信条:你的意思是'进步'?这只是一个.NET属性,而不是'struct'。是的,这是封装的一个重要部分,听起来像是这个答案很可能对你来说是新的。如果您遇到问题或感到困惑,请告诉我,我会尽我所能提供帮助。 – 2010-09-16 14:40:31

+0

好,所以我的主线程将运行UI,并且我使用后台工作人员来调用我的控制器方法,然后调用自定义类中的方法与循环。 我是否需要在UI类中运行循环以反复调用backgroundWorker.ReportProgress?还是自动更新? 谢谢你的耐心答复,我从来没有做过线程之前。 – 2010-09-16 14:43:05

1

我通常有一个类在UI上进行调用检查。 UI - >“UpdaterClass” - >其他类。

Updater类具有预定义的方法和对UI控件的引用。所以Updater.StepProgressBar()就是我所说的步进UI进度条。我将Updater类引用传递给任何需要直接更新UI的类。

这样,来自不同线程的所有UI更新都由一个类来处理。不是最通用的方式来实现它,但它永远不会失败。

实施例伪码:

class Updater() 
{ 

    public ProgressBar pb; 

    delegate void UpdateProgressBar(); 

    public StepProgressBar() 
    { 
    if(pb.InvokeRequired) 
    { 
      BeginInvoke(new UpdateProgressBar(this.StepProgressBar); 
    } 
    else 
    { 
      pb.Step(); 
     } 
    } 

} 

类似的东西。

+0

这对我来说并不实际,因为我有许多访问多个UI的控制器类,每个控制器下面有多个库。 – 2010-09-16 14:46:58

1

您可以使用委托。当后台进程创建自定义类时,绑定从自定义类调用的委托来报告更新。然后,您可以在UI层对该呼叫作出反应,并从那里更新进度栏。

例如(警告,伪代码):

MyCustomClass class = new MyCustomClass(); 
class.ProgressUpdated += (s,e)=>{ /* update UI */}; 
class.StartLoop(); 
+0

对不起以前从未使用过代表,我必须先阅读他们。 – 2010-09-16 14:45:13

+0

委托,事件和线程有什么区别? – 2010-09-16 14:54:04

+0

@丹涛给出了一个很好的例子来说明如何做到这一点。我建议你在尝试做这件事之前做一些外部事件和代表的阅读。后台处理有其自己的缺陷,在进入任何过于复杂的事情之前需要知道如何避免。 – Robaticus 2010-09-16 15:03:29