通用的异步处理类和进度通知类及其示例
在上文《我的界面进度条异步显示模式》中,我提到了使用异步处理显示进度条的时候,我觉得用起来比较顺手的一种组织代码的方法,相比起来,这种方法的最大特点就是把代码尽量地从界面层剥离,并且让界面之间的关联尽可能少些。
我在处理过程中使用了一个封装了异步线程处理的一个抽象类,这个抽象类实现了异步处理的 Start,Abort, Pause 和 Resume 接口,大家用它来实现异步处理的时候,就可以象玩秒表一样随意地控制这些处理过程了。完整的代码如下:
在处理进度变化的时候,我使用了一个抽象的接口 IProgress,这个抽象接口提供外部对进度的查询功能,接口定义如下:
在具体实现的时候,可以看我的 ProgressMoniter 的代码,这个是利用一个单独的线程来定期轮询 IProgress 接口进度变化,然后产生事件通知,是最好的说明例子,如果有人想修改成非轮询的方式,也很容易。
我在处理过程中使用了一个封装了异步线程处理的一个抽象类,这个抽象类实现了异步处理的 Start,Abort, Pause 和 Resume 接口,大家用它来实现异步处理的时候,就可以象玩秒表一样随意地控制这些处理过程了。完整的代码如下:
public abstract class AsyncWorker
{
public enum WorkState{Ready, Working, Pause,Resume,Aborted, Done, Error}
private WorkState m_State;
private bool m_Wait;
private Thread m_Thread;
protected AsyncWorker(bool wait)
{
m_State = WorkState.Ready;
m_Wait = wait;
m_Thread = new Thread(new ThreadStart(Work));
}
public void Start()
{
OnStateChangedSync(WorkState.Ready);
m_Thread.Start();
while( m_Wait && m_Thread.IsAlive )
{
OnIdle();
Thread.Sleep(200);
}
}
public void Pause()
{
if( m_State == WorkState.Working)
{
m_Thread.Suspend();
m_State = WorkState.Pause;
OnStateChanged(WorkState.Pause);
}
}
public void Resume()
{
if( m_State == WorkState.Pause )
{
m_State = WorkState.Working;
m_Thread.Resume();
OnStateChanged(WorkState.Resume);
}
}
public void Abort()
{
if( m_State == WorkState.Working || m_State == WorkState.Pause )
{
m_Thread.Abort();
m_State = WorkState.Aborted;
OnStateChanged(WorkState.Aborted);
}
}
private void Work()
{
try
{
m_State = WorkState.Working;
OnStateChangedSync(WorkState.Working);
DoWork();
m_State = WorkState.Done;
OnStateChanged(WorkState.Done);
}
catch (Exception e)
{
m_State = WorkState.Error;
OnError(e);
OnStateChanged(WorkState.Error);
}
}
protected abstract void DoWork();
private void OnStateChangedSync(WorkState state)
{
if( StateChanged != null )
StateChanged(this, state);
}
private void OnStateChanged(WorkState state)
{
if( StateChanged != null )
StateChanged.BeginInvoke(this, state, null, null);
}
protected void OnIdle()
{
if( Idle != null )
{
lock(this) // 有可能会很高频率调用
Idle(this);
}
}
protected void OnError(Exception e)
{
if( Error != null )
Error.BeginInvoke(this, e, null, null);
}
public delegate void StateChangedEventHandler(AsyncWorker sender, WorkState state);
public delegate void IdleEventHandler(AsyncWorker sender);
public delegate void ErrorEventHandler(AsyncWorker sender, Exception e);
public event StateChangedEventHandler StateChanged;
public event IdleEventHandler Idle;
public event ErrorEventHandler Error;
}
{
public enum WorkState{Ready, Working, Pause,Resume,Aborted, Done, Error}
private WorkState m_State;
private bool m_Wait;
private Thread m_Thread;
protected AsyncWorker(bool wait)
{
m_State = WorkState.Ready;
m_Wait = wait;
m_Thread = new Thread(new ThreadStart(Work));
}
public void Start()
{
OnStateChangedSync(WorkState.Ready);
m_Thread.Start();
while( m_Wait && m_Thread.IsAlive )
{
OnIdle();
Thread.Sleep(200);
}
}
public void Pause()
{
if( m_State == WorkState.Working)
{
m_Thread.Suspend();
m_State = WorkState.Pause;
OnStateChanged(WorkState.Pause);
}
}
public void Resume()
{
if( m_State == WorkState.Pause )
{
m_State = WorkState.Working;
m_Thread.Resume();
OnStateChanged(WorkState.Resume);
}
}
public void Abort()
{
if( m_State == WorkState.Working || m_State == WorkState.Pause )
{
m_Thread.Abort();
m_State = WorkState.Aborted;
OnStateChanged(WorkState.Aborted);
}
}
private void Work()
{
try
{
m_State = WorkState.Working;
OnStateChangedSync(WorkState.Working);
DoWork();
m_State = WorkState.Done;
OnStateChanged(WorkState.Done);
}
catch (Exception e)
{
m_State = WorkState.Error;
OnError(e);
OnStateChanged(WorkState.Error);
}
}
protected abstract void DoWork();
private void OnStateChangedSync(WorkState state)
{
if( StateChanged != null )
StateChanged(this, state);
}
private void OnStateChanged(WorkState state)
{
if( StateChanged != null )
StateChanged.BeginInvoke(this, state, null, null);
}
protected void OnIdle()
{
if( Idle != null )
{
lock(this) // 有可能会很高频率调用
Idle(this);
}
}
protected void OnError(Exception e)
{
if( Error != null )
Error.BeginInvoke(this, e, null, null);
}
public delegate void StateChangedEventHandler(AsyncWorker sender, WorkState state);
public delegate void IdleEventHandler(AsyncWorker sender);
public delegate void ErrorEventHandler(AsyncWorker sender, Exception e);
public event StateChangedEventHandler StateChanged;
public event IdleEventHandler Idle;
public event ErrorEventHandler Error;
}
在处理进度变化的时候,我使用了一个抽象的接口 IProgress,这个抽象接口提供外部对进度的查询功能,接口定义如下:
/// <summary>
/// 反映进度的变化的接口
/// </summary>
public interface IProgress
{
int Total{get;}
int CurrentProgress{get;}
string Description{get;}
}
/// 反映进度的变化的接口
/// </summary>
public interface IProgress
{
int Total{get;}
int CurrentProgress{get;}
string Description{get;}
}
在具体实现的时候,可以看我的 ProgressMoniter 的代码,这个是利用一个单独的线程来定期轮询 IProgress 接口进度变化,然后产生事件通知,是最好的说明例子,如果有人想修改成非轮询的方式,也很容易。
public class ProgressMoniter : AsyncWorker
{
public delegate void ProgressEventHandler(string text, int percent);
public event ProgressEventHandler Progress;
IProgress m_Progress;
private bool m_Exit;
public bool Exit { get { return m_Exit; } set { m_Exit = value; } }
public ProgressMoniter(IProgress progress) : base(false)
{
m_Progress = progress;
m_Exit = false;
}
protected override void DoWork()
{
while( !m_Exit )
{
lock(m_Progress)
OnProgress(m_Progress.Description, m_Progress.Total, m_Progress.CurrentProgress);
Thread.Sleep(200);
}
}
private void OnProgress(string description, int total, int progress)
{
if( Progress != null )
Progress.BeginInvoke(description, (int)((long)progress * 100 / (long)total), null, null);
}
}
{
public delegate void ProgressEventHandler(string text, int percent);
public event ProgressEventHandler Progress;
IProgress m_Progress;
private bool m_Exit;
public bool Exit { get { return m_Exit; } set { m_Exit = value; } }
public ProgressMoniter(IProgress progress) : base(false)
{
m_Progress = progress;
m_Exit = false;
}
protected override void DoWork()
{
while( !m_Exit )
{
lock(m_Progress)
OnProgress(m_Progress.Description, m_Progress.Total, m_Progress.CurrentProgress);
Thread.Sleep(200);
}
}
private void OnProgress(string description, int total, int progress)
{
if( Progress != null )
Progress.BeginInvoke(description, (int)((long)progress * 100 / (long)total), null, null);
}
}
公众号:老翅寒暑