using System; using System.Drawing; using System.Threading; using System.Windows.Forms; namespace UAS_MES_NEW.CustomControl { public partial class ProcessBar : UserControl { public delegate void TaskHandler(ref float percentage); private Thread _monitorThread = null; private Thread _workerThread = null; private float _percentage = 0f; private ProcessBarStatue _currentStatue = ProcessBarStatue.UnStarted; private TaskHandler _task = null; public ProcessBar() { InitializeComponent(); this._monitorThread = new Thread(new ThreadStart(Monitor)); } /// /// 任务委托 /// 多次对该属性赋值会造成不必要的浪费 /// public TaskHandler Task { set { //任务线程 通过传入引用类型参数获得实时的进度变更 this._workerThread = new Thread(() => value(ref _percentage)); this._task = value; } } /// /// 外部也可以实时获取当前任务进度 /// public float Percentage { get { return this._percentage; } } /// /// 外部实时获取当前任务状态 /// public ProcessBarStatue CurrentStatue { get { return this._currentStatue; } } public void Run() { if (this._workerThread == null) { throw new NullReferenceException("Task委托不能为空!"); } //初次启动 需要同时启动工作线程和监听线程 if (this._currentStatue == ProcessBarStatue.UnStarted) { _monitorThread.IsBackground = true; _monitorThread.Start(); _workerThread.IsBackground = true; _workerThread.Start(); this._currentStatue = ProcessBarStatue.Running; } //被终止后第二次启动 只需要重启工作线程就可以 else if (this._currentStatue == ProcessBarStatue.Aborted) { this._currentStatue = ProcessBarStatue.Running; //若原工作线程已经终止 则重新初始化工作线程 if (this._workerThread.ThreadState == ThreadState.Aborted) { this._workerThread = null; this._workerThread = new Thread(() => _task(ref _percentage)); } _workerThread.IsBackground = true; _workerThread.Start(); } else { throw new InvalidOperationException("已经开始的任务无法再次开始!"); } } public void Stop() { if (_workerThread == null) { throw new NullReferenceException("Task委托不能为空!"); } if (this._currentStatue == ProcessBarStatue.Aborted) { throw new InvalidOperationException("已经终止的操作无法暂停!"); } if (this._currentStatue != ProcessBarStatue.Suspended) { //_workerThread.Suspend(); //_monitorThread.Suspend(); this._currentStatue = ProcessBarStatue.Suspended; } } public void Resume() { if (_workerThread == null) { throw new NullReferenceException("Task委托不能为空!"); } if (this._currentStatue == ProcessBarStatue.Aborted) { throw new InvalidOperationException("已经终止的操作无法继续!"); } if (this._currentStatue == ProcessBarStatue.Suspended) { //_monitorThread.Resume(); //_workerThread.Resume(); this._currentStatue = ProcessBarStatue.Running; } } public void Abort() { if (this._workerThread == null) { throw new NullReferenceException("Task委托不能为空!"); } if (this._currentStatue != ProcessBarStatue.Aborted) { //若之前为Suspended状态 则需要先Resume才可以终止工作线程 this.Resume(); _workerThread.Abort(); this._currentStatue = ProcessBarStatue.Aborted; } } private void Monitor() { //外层无限循环 监听标志变量的改变 while (true) { //当UI调用Start方法时监听线程首次启动并设置标志变量为Running if (this._currentStatue == ProcessBarStatue.Running) { //在此循环中监听_percetage变量的改变情况 由于该变量作为引用参数传入Task委托 所以可以得到实时的进度 while (this._percentage <= 1f) { //调用Draw方法更新UI using (var graphic = pictureBox1.CreateGraphics()) { if (this.pictureBox1.InvokeRequired) { this.Invoke(new Action(() => Draw(this._percentage, graphic))); } else { this.Draw(this._percentage, graphic); } Thread.Sleep(10);//重绘间隔为10ms //当发现标志变量改变为终止时跳出 回到最外层监听标志变量的循环 if (this._currentStatue == ProcessBarStatue.Aborted) { this._percentage = 0f;//将百分比重置为0 if (this.pictureBox1.InvokeRequired)//将绘图区清空 { this.Invoke(new Action(() => this.Clear(graphic))); } else { this.Clear(graphic); } break; } } } } } } /// /// 如果要更改进度条显示的形式 则继承当前类 重写Draw方法 /// /// /// protected virtual void Draw(float percentage, Graphics graphic) { graphic.FillRectangle(Brushes.Black, 0f, 0f, _percentage * pictureBox1.Width, pictureBox1.Height); } /// /// 若需要更改进度条默认颜色 背景 则继承当前类 重写Clear方法 /// /// private void Clear(Graphics graphic) { graphic.Clear(Color.White); } public enum ProcessBarStatue { UnStarted, Running, Suspended, Aborted } } }