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

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

在处理进度变化的时候,我使用了一个抽象的接口 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), null, null);
        }
    }

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

  1. Notification使用详解之三:通过服务更新进度通知在Activity中监听服务进度

    为什么80%的码农都做不了架构师?>>>    上次我们讲到如何实现一个可更新的进度通知,实现的方式是启动一个线程模拟一个下载任务,然后根据任务进度向UI线程消息队列发送进度消息,U ...

  2. STM32F103系列实战之通用同步异步收发器(USART)

    通用同步/异步收发器(USART) STM32F103xC. STM32F103xD和STM32F103xE增强型系列产品中,内置了3个通用同步/异步收发器(USART1. USART2和USART3 ...

  3. PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)...

    源码地址:https://github.com/Tinywan/PHP_Experience 测试环境配置: 环境:Windows 7系统 .PHP7.0.Apache服务器 PHP框架:ThinkP ...

  4. php插入数据进度条,PHP导入进度条类

    这篇文章主要介绍了关于PHP导入进度条类,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 最近在做一个客户导入的功能,整理的一个导入的进度条类:<?php /** * @File ...

  5. UART 和 USART 的区别 == 通用异步收发传输器 通用同步/异步串行接收/发送器

    UART 通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器,是电脑硬件的一部分.它将要传输的资料在串 ...

  6. vbs获取程序窗体句柄_[VBA][高阶应用][类模块]自绘窗体进度条类cProgressBar.cls

    纯API自绘窗体的进度条类,废话少说,直接上代码 这个进度条类的调用方式: Private Declare Function FindWindow Lib "user32.dll" ...

  7. MIUI通知类短信权限的坑

    MIUI的坑爹设计还真不少.比如说,MIUI手机不插SIM卡就不能USB调试安装应用,好,插,结果又让你先登录小米账号(无话可说).MIUI权限申请也是坑! 就拿READ_SMS这个权限来说,按照安卓 ...

  8. 镂空文字、类歌词进度显示文字

    Demo详见GitHub:JXTMarkLabel 镂空文字 - JXTHollowOutLabel 镂空文字效果的实现基于drawRect重绘,具体参考了两篇帖子: Drawing a path w ...

  9. 17、STM8S通用同步异步收发器(UART)

    文章目录 1.概述 2.串口主要特点 3.UART功能描述 4.UART主要特点 5.异步串行通信的字符格式 6.串行通信的传送速率 1.概述   STM8S 微控制器家族的通用同步异步收发器(UAR ...

最新文章

  1. 慕课python课后作业_python基础1习题练习
  2. mess组网 中继_取代中继/子母路由 堪称最上乘的Mesh组网方式了解下
  3. java 导出excel二维表,如何轻松将EXCEL二维统计表转为数据清单?
  4. mac如何将本地服务暴露到外网?
  5. 03 unix 设计哲学和流重定向
  6. java中sql 语句格式转换_Java字符串转Sql语句In格式工具方法
  7. java 上文件传示例_Java解压缩文件示例
  8. Excel按某一列排序
  9. 发生内部错误。请与 microsoft 支持部门联系。_设计变更、工程签证、确认单、工程洽商、联系单、会签的区别,一文搞懂...
  10. c# 时间格式化为英文_C#格式化英文字母的三种方法
  11. 51单片机连接ESP8266串口WiFi模块
  12. 高等数学张宇18讲 第六讲 零点问题、微分不等式
  13. 五大赛场十大赛题百万奖金!山东省第二届数据应用创新创业大赛等你来!
  14. HUAWEI Mate40Pro解除账号忘记密码ID强制刷机鸿蒙系统激活锁能解开吗
  15. 图片打印设置之适应边框打印
  16. lda2vec (2)
  17. 港湾公园 Haven Park for Mac(好玩的探索建造冒险游戏)
  18. 宝塔平台配置JeecgBoot
  19. Windows10:关于触摸板的驱动不适用的问题
  20. 如何高效构建保险业场景化数据分析体系-承保和理赔

热门文章

  1. Vue 2.x + Webpack 4.x的那些事---萌新必备
  2. TabActivity 切换到后台遇到的问题
  3. Android学习起步 - 新建工程及相关
  4. 反向传播算法 Backpropagation Algorithm
  5. Android中menu详解(转)
  6. 入门Java菜鸟,JDK和Eclipse的安装一定要知道
  7. 关于着色器LinearGradient的使用
  8. java代码运行linux shell操作
  9. 生成器模式 - 让配置代码更优雅
  10. sql 查看某用户的连接数 以及 如何删除该用户的会话