在C#,windows窗体中创建.net应用程序。如何在100循环循环的每个循环中更新进度条1步? (我正在处理循环中的Excel工作表。) 进度条控件位于UI类中,它连接到连接到自定义类 (MVC模式)的控制器类。循环在自定义类中。 我是否需要在每种方法中一直发送UI类实例还是有更好的方法?如何在每个循环周期内一步更新进度条? C#
当前进度条在循环结束后更新。 Application.doevents和.update或.refresh不起作用。
在C#,windows窗体中创建.net应用程序。如何在100循环循环的每个循环中更新进度条1步? (我正在处理循环中的Excel工作表。) 进度条控件位于UI类中,它连接到连接到自定义类 (MVC模式)的控制器类。循环在自定义类中。 我是否需要在每种方法中一直发送UI类实例还是有更好的方法?如何在每个循环周期内一步更新进度条? C#
当前进度条在循环结束后更新。 Application.doevents和.update或.refresh不起作用。
说下面是你的类负责做循环工作。添加一个事件来指示你的进度。然后从你的用户界面简单地处理该事件并相应地更新进度条。
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)。
只是一个例子,可以实现这种事情。
什么叫你在哪里有控制私有变量的公共结构?那是封装吗? – 2010-09-16 14:36:30
@hi科技信条:你的意思是'进步'?这只是一个.NET属性,而不是'struct'。是的,这是封装的一个重要部分,听起来像是这个答案很可能对你来说是新的。如果您遇到问题或感到困惑,请告诉我,我会尽我所能提供帮助。 – 2010-09-16 14:40:31
好,所以我的主线程将运行UI,并且我使用后台工作人员来调用我的控制器方法,然后调用自定义类中的方法与循环。 我是否需要在UI类中运行循环以反复调用backgroundWorker.ReportProgress?还是自动更新? 谢谢你的耐心答复,我从来没有做过线程之前。 – 2010-09-16 14:43:05
我通常有一个类在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();
}
}
}
类似的东西。
这对我来说并不实际,因为我有许多访问多个UI的控制器类,每个控制器下面有多个库。 – 2010-09-16 14:46:58
您可以使用委托。当后台进程创建自定义类时,绑定从自定义类调用的委托来报告更新。然后,您可以在UI层对该呼叫作出反应,并从那里更新进度栏。
例如(警告,伪代码):
MyCustomClass class = new MyCustomClass();
class.ProgressUpdated += (s,e)=>{ /* update UI */};
class.StartLoop();
对不起以前从未使用过代表,我必须先阅读他们。 – 2010-09-16 14:45:13
委托,事件和线程有什么区别? – 2010-09-16 14:54:04
@丹涛给出了一个很好的例子来说明如何做到这一点。我建议你在尝试做这件事之前做一些外部事件和代表的阅读。后台处理有其自己的缺陷,在进入任何过于复杂的事情之前需要知道如何避免。 – Robaticus 2010-09-16 15:03:29
在较低级别的活动发布广告进展情况时出现了什么问题? – Joey 2010-09-16 13:38:58
对不起,我不明白你刚刚说的。进度条被定义在一个更高的类中,如果我更新低级类的值,上层类将如何知道?我不得不将ui类实例或进度条实例传递到较低级别。 – 2010-09-16 13:45:46
我不确定,但如果更新发生延迟,它几乎听起来像是一个线程问题。你在使用invoke吗(如果有必要)? – 2010-09-16 13:49:19