我的界面进度条异步显示模式
系统的注册表坏了,又不想重装,于是考虑编一个程序来比较一下注册表的变化(我每装一个重要软件都会备份注册表)。在实际编程的时候,因为处理注册表的时间比较长,需要显示一个进度条,而且要异步处理,避免界面长时间没有响应的问题。
原来的处理方法采用过如下的两种(以下是伪代码):
另外一种是觉得使用时钟不好,绕来绕去太麻烦,又想把调用 WorkThread 部分代码放到 Form1 中,但是如此一来,ShowDialog 就不能用了,代码变成了如下:
但是使用过程中发现窗口这样的关系就变得很尴尬,而且,就这样的代码,我始终无法把ProgressForm中的 “中断操作” 按钮的代码找到一个满意的实现方法。
最后,经过重新的考虑和设计,最终的代码把 WorkThread 设计了一个通用的接口,屏蔽了使用线程的一些繁琐,并且提供了 Start, Pause, Resume,Abort 接口,并通过事件发送对外通知。另外,取消频繁调用进度通知的代码,提供了一个进度查询接口 IProgress,由专门的进度监控线程ProgressMoniter 来监视进度并通知ProgressForm刷新界面。最后的外部代码如下:
其他部分的代码和实现在下一篇文章里,等一下我就写。
请看《通用的异步处理类和进度通知类及其示例》。
原来的处理方法采用过如下的两种(以下是伪代码):
class Form1
{
void OnStartButtonClick()
{
ProgressForm prog = new ProgressForm();
// 预处理
prog.ShowDialog();
// 其他处理
}
}
class ProgressForm
{
private Timer m_Timer; //设置时钟, 100ms
void TimerTick() // 时钟触发
{
m_Timer.Enable = false; // 时钟只需要用一次
// 以下开始正式的处理过程
WorkThread th = new WorkThread();
th.ProgressEvent += new ProgressEvent(ProgressCallback);
//
}
void ProgressCallback(){ }
}
{
void OnStartButtonClick()
{
ProgressForm prog = new ProgressForm();
// 预处理
prog.ShowDialog();
// 其他处理
}
}
class ProgressForm
{
private Timer m_Timer; //设置时钟, 100ms
void TimerTick() // 时钟触发
{
m_Timer.Enable = false; // 时钟只需要用一次
// 以下开始正式的处理过程
WorkThread th = new WorkThread();
th.ProgressEvent += new ProgressEvent(ProgressCallback);
//
}
void ProgressCallback(){ }
}
另外一种是觉得使用时钟不好,绕来绕去太麻烦,又想把调用 WorkThread 部分代码放到 Form1 中,但是如此一来,ShowDialog 就不能用了,代码变成了如下:
class Form1
{
ProgressForm prog;
void OnStartButtonClick()
{
prog = new ProgressForm();
// 预处理
this.Enabled = false; // 禁止自身,保证 ProgressForm 在窗口前面
prog.Show();
// 开始处理
WorkThread th = new WorkThread();
th.ProgressEvent += new ProgressEvent(ProgressCallback);
// 其他处理
}
void ProgressCallback()
{
prog.DisplayProgress(total, percent, text);
}
}
class ProgressForm
{
public void DisplayProgress( )
{
// 刷新进度条
}
}
{
ProgressForm prog;
void OnStartButtonClick()
{
prog = new ProgressForm();
// 预处理
this.Enabled = false; // 禁止自身,保证 ProgressForm 在窗口前面
prog.Show();
// 开始处理
WorkThread th = new WorkThread();
th.ProgressEvent += new ProgressEvent(ProgressCallback);
// 其他处理
}
void ProgressCallback()
{
prog.DisplayProgress(total, percent, text);
}
}
class ProgressForm
{
public void DisplayProgress( )
{
// 刷新进度条
}
}
但是使用过程中发现窗口这样的关系就变得很尴尬,而且,就这样的代码,我始终无法把ProgressForm中的 “中断操作” 按钮的代码找到一个满意的实现方法。
最后,经过重新的考虑和设计,最终的代码把 WorkThread 设计了一个通用的接口,屏蔽了使用线程的一些繁琐,并且提供了 Start, Pause, Resume,Abort 接口,并通过事件发送对外通知。另外,取消频繁调用进度通知的代码,提供了一个进度查询接口 IProgress,由专门的进度监控线程ProgressMoniter 来监视进度并通知ProgressForm刷新界面。最后的外部代码如下:
class Form1
{
void OnStartButtonClick()
{
ProgressForm prog = new ProgressForm();
// 预处理
// 生成工作线程
WorkThread m_Worker = new WorkThread();
m_Worker.Idle += new IdleEventHandler(m_Worker_Idle);
m_Worker.Error += new ErrorEventHandler(m_Worker_Error);
m_Worker.StateChanged += new StateChangedEventHandler(m_Worker_StateChanged);
// 生成监控线程
ProgressMoniter m_Moniter = new ProgressMoniter(m_Worker);
prog.Assign(m_Moniter); // ProgressForm 关联监控线程的进度变化事件
m_Worker.Start(); // 开始工作
m_Moniter.Start(); // 开始监控进度
prog.ShowDialog(); // ShowDialog显示,这下不用 this.Enable = false 了
// ShowDialog会一直等待工作完成之后才返回,然后作其他处理
}
}
class ProgressForm
{
public void Assign(ProgressMoniter moniter)
{
DisplayProgress("ready", 0);
this.btnCancel.Enabled = true; // 允许中断
m_Worker = moniter;
moniter.Progress += new ProgressEventHandler(DisplayProgress); // 挂接事件
}
public void DisplayProgress( )
{
// 刷新进度条
}
}
{
void OnStartButtonClick()
{
ProgressForm prog = new ProgressForm();
// 预处理
// 生成工作线程
WorkThread m_Worker = new WorkThread();
m_Worker.Idle += new IdleEventHandler(m_Worker_Idle);
m_Worker.Error += new ErrorEventHandler(m_Worker_Error);
m_Worker.StateChanged += new StateChangedEventHandler(m_Worker_StateChanged);
// 生成监控线程
ProgressMoniter m_Moniter = new ProgressMoniter(m_Worker);
prog.Assign(m_Moniter); // ProgressForm 关联监控线程的进度变化事件
m_Worker.Start(); // 开始工作
m_Moniter.Start(); // 开始监控进度
prog.ShowDialog(); // ShowDialog显示,这下不用 this.Enable = false 了
// ShowDialog会一直等待工作完成之后才返回,然后作其他处理
}
}
class ProgressForm
{
public void Assign(ProgressMoniter moniter)
{
DisplayProgress("ready", 0);
this.btnCancel.Enabled = true; // 允许中断
m_Worker = moniter;
moniter.Progress += new ProgressEventHandler(DisplayProgress); // 挂接事件
}
public void DisplayProgress( )
{
// 刷新进度条
}
}
其他部分的代码和实现在下一篇文章里,等一下我就写。
请看《通用的异步处理类和进度通知类及其示例》。
公众号:老翅寒暑