通用的异步处理类和进度通知类及其示例

在上文《我的界面进度条异步显示模式》中,我提到了使用异步处理显示进度条的时候,我觉得用起来比较顺手的一种组织代码的方法,相比起来,这种方法的最大特点就是把代码尽量地从界面层剥离,并且让界面之间的关联尽可能少些。

我在处理过程中使用了一个封装了异步线程处理的一个抽象类,这个抽象类实现了异步处理的 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, nullnull);
        }


        
protected void OnIdle()
        
{
            
if( Idle != null )
            
{
                
lock(this)        // 有可能会很高频率调用
                    Idle(this);
            }

        }


        
protected void OnError(Exception e)
        
{
            
if( Error != null )
                Error.BeginInvoke(
this, e, nullnull);
        }


        
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;}
    }


在具体实现的时候,可以看我的 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), nullnull);
        }

    }

posted on 2005-03-09 15:44  老翅寒暑  阅读(2982)  评论(9编辑  收藏  举报

导航