写在前面
C# Tips是博主开启的第一个项目,以C#为示例语言,旨在普及编程技巧、经典算法以及计算机视觉、图形学知识。
进度条的日常
只要是接触过计算机的同学,对于进度条一定不陌生。
有时候它是这样的(图片来自网络):

有时候是这样的(图片来自网络):

那么疑问来了,为什么有的进度条能学会“百米冲刺”,而有的进度条却像乌龟一样缓缓前行?为解决这个疑问,需要了解进度条的含义以及工作机制,然后我们可以利用VS的progress bar控件轻松定义属于自己的进度条。
进度条的含义
进度条是一种定量反映流程进度的控件。进度条的增加速度体现了走完流程所耗费的时间,进度条的增加次数体现了完成流程所需的步骤,进度条本身的数值体现了当前所完成的进度。
为实现以上要求,C#中progress bar控件拥有以下属性:
| 属性 | 含义 |
|---|---|
| Minimum | 进度条范围的最小值(进度条完全未填满状态) |
| Maximum | 进度条范围的最大值(进度条完全填满状态) |
| Value | 进度条当前值 |
进度条的工作机制
为了更好地量化时间流逝,progress bar将开启流程的时间记为Minimum(通常为0),结束流程的时间记为Maximum,Maximum-Minimum即为走完流程所耗费的等价时间,或者将Maximum理解为流程能够拆解的步骤数量,每完成一个步骤,Value便增加n个单位的时间,每一个单位时间表示的实际时间不尽相同,与完成上一个步骤所需的实际时间有关。
进度条的实现
与按钮、文本等控件不同,progress bar需要实时更新,放置在主窗体的控件会因为主线程(UI线程)阻塞而无法及时更新,所以最好的做法是将耗时方法放到另外一个线程中,然后根据另一个线程中耗时方法的执行进度更新主线程中progress bar的Value值。
但由此会引发两个问题:
- 如何创建另一个线程?
- 非主线程该怎么控制主线程中的控件才不会出错呢?
多线程问题
C#在System.Threading中提供了一系列创建线程的方法:
开启线程的方法Method返回值必须为void,参数为object类型或无参,如果需要传递多个参数,可将参数封装到类或结构体中,直接传入对象即可。
private void Method(object parameters)
Thread thread1 = new Thread(new ParameterizedThreadStart(Method));
thread1.IsBackground = true;
thread1.Start(parameters);
或者
private void Method()
Thread thread1 = new Thread(new ThreadStart(Method));
thread1.IsBackground = true;
thread1.Start();
跨线程问题
为解决第二个问题,首先定义一个设置progress bar值的委托:
private delegate void pbDelegate(int value);
然后再写一个包含Control.Invoke的方法:
/// <summary>
/// 多线程设置进度条的值
/// </summary>
/// <param name="value">值</param>
private void SetPbValue(int value)
{
if (progressBar1.InvokeRequired)
Invoke(new pbDelegate(SetPbValue), new object[] { value });
else
{
if (value != -1)
progressBar1.Value = value;
else
progressBar1.Visible = false;
}
}
上面代码的含义是:
- 如果progress bar在主线程中,直接更新progress bar的值,当值为-1时指示progress bar不可见;
- 如果progress bar在非主线程中,利用Invoke执行委托,效果将会与在主线程中一致。
本文深入解析C#中进度条控件的工作原理及其实现方法,介绍如何利用progressbar控件反映流程进度,探讨其属性及多线程下如何更新进度条值。
828

被折叠的 条评论
为什么被折叠?



