首页 > GAME > 游戏 > 正文

张家界济勾电子有限公司,亳州啄讲信用担保有限公司,咸宁烦瓷郴汽车服务有限公司

马红俊呵呵一笑,道:“我也算了吧。我和三哥一样,都喜欢自由。终于毕业了,我想在大陆上四处转转,增长见闻。以后可能会回史莱克学院帮我老师。”

中国钱是谁借给美国的

旋即在老顽童瞪大的目光注视下刘皓直接一手伸到脖子后面拉着自己的脖子凭空将人提起来,不是提起一瞬间,而是提起来一直没有掉下来
在这三千年时间里面每一个大能的表情都精彩无比,最精彩的特别是准提和接引,两个时而大笑,时而苦涩,甚至哇哇大哭起来,这完全不像是一个准圣强者该有的样子反而好像是神经出了问题的普通人。

盗一最终是摇了摇头,首先她在那里也是孤苦伶仃一个人,在什么地方都一样,何况这个世界也没什么不好的。其次,她现在已经嫁给叶扬了,自然是嫁鸡随鸡,嫁狗随狗了。当然要跟着叶扬走了。

上面的对象


在一些耗时的操作过程中,在长时间运行时可能会导致用户界面 (UI) 处于停止响应状态,用户在这操作期间无法进行其他的操作,为了不使UI层处于停止响应状态,我们倾向推荐用户使用BackgroundWorker来进行处理,这个后台的线程处理,可以很好的实现常规操作的同时,还可以及时通知UI,包括当前处理信息和进度等,这个BackgroundWorker的处理在百度里面也是有很多使用的介绍,本篇随笔主要是做一些自己的使用总结,希望也能给读者提供一个参考。

在使用BackgroundWorker的过程中,我们可以定义自己的状态参数信息,从而实现线程状态的实时跟踪以及进度和信息提示,方便我们及时通知UI进行更新。本篇随笔主要针对一些数据采集过程的处理,在网上采集特定的数据往往需要耗时几个小时以上,如果采用常规的同步操作,比较麻烦,而如果引入一些SmartThreadPool这些第三方类库有显得臃肿,而且资源耗费的也很严重,因此使用BackgroundWorker相对比较轻型的方案比较吸引我。

采集的数据处理

例如是我采集数据的一个局部界面,主要是根据一些参数进行数据的采集,采集过程可以通过状态栏和右边的标签进行反馈,在状态栏显示采集进度等信息,实现比较友好的信息显示。

一般我们定义后台线程处理,可以在该窗体定义一个变量即可,如下代码所示。

        private BackgroundWorker worker = new BackgroundWorker();

然后就是对这个后台线程处理对象的一些事件进行实现即可,如下代码所示

    public partial class MainFrame : BaseForm
    {
        /// <summary>
        /// 增加一个变量来记录线程状态
        /// </summary>
        private bool IsThreadRunning = false;
        private BackgroundWorker worker = new BackgroundWorker();

        public MainFrame()
        {
            InitializeComponent();

            Portal.gc.InitData();

            worker.WorkerSupportsCancellation = true;   //支持取消
            worker.WorkerReportsProgress = true;        //支持报告进度
            worker.DoWork += worker_DoWork;             //处理过程
            worker.RunWorkerCompleted += worker_RunWorkerCompleted; //完成操作
            worker.ProgressChanged += worker_ProgressChanged;       //报告进度
        }

例如进度条的通知,主要就是计算总任务的数量,以及当前完成的人数数量,我们实现代码如下所示

        /// <summary>
        /// 进度条的通知
        /// </summary>
        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.barProgress.EditValue = e.ProgressPercentage;
            CollectStateInfo stateInfo = e.UserState as CollectStateInfo;
            if (stateInfo != null)
            {
                var message = string.Format("正在采集 {0} 的 {1} , 项目名称为:{2}", stateInfo.TotalRecords, stateInfo.CompletedRecord + 1, stateInfo.CurrentItemName);
                this.lblTips.Text = message;
                this.barTips.Caption = message;

                //记录运行位置
                JobParameterHelper.SaveData(new CurrentJobParameter(stateInfo));
            }
        }

这里我们看到了,这个里面使用了一个自定义的状态参数CollectStateInfo ,这个是我们用来在后台进程处理过程中传递的一个对象,可以记录当前采集的相关信息,CollectStateInfo 类的定义如下所示。

    /// <summary>
    /// 状态对象数据
    /// </summary>
    public class CollectStateInfo
    {
        /// <summary>
        /// 当前期数(年份+期数)
        /// </summary>
        public string YearQSNumber { get; set; }

        /// <summary>
        /// 任务开始时间
        /// </summary>
        public DateTime StartTime { get; set; }

        private DateTime m_EndTime = DateTime.Now;

        /// <summary>
        /// 任务开始时间
        /// </summary>
        public DateTime EndTime
        {
            get
            {
                return m_EndTime;
            }
            set
            {
                //设置结束时间的时候,获取耗时
                m_EndTime = value;
                this.TimeSpanUsed = value.Subtract(this.StartTime);
            }
        }

        /// <summary>
        /// 任务用时
        /// </summary>
        public TimeSpan TimeSpanUsed { get; set; }

        /// <summary>
        /// 任务数量
        /// </summary>
        public int TotalRecords { get; set; }

        private int m_CompletedRecord = 0;

        /// <summary>
        /// 完成数量
        /// </summary>
        public int CompletedRecord
        {
            get
            {
                return m_CompletedRecord;
            }
            set
            {
                m_CompletedRecord = value;
                if (TotalRecords > 0)
                {
                    this.CurrentProgress = Convert.ToInt32(value * 100.0 / TotalRecords);
                }
            }
        }

        /// <summary>
        /// 当前进度
        /// </summary>
        public int CurrentProgress { get; set; }

        /// <summary>
        /// 当前采集的项目
        /// </summary>
        public string CurrentItemName { get; set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        /// <param name="total"></param>
        public CollectStateInfo()
        {
            this.StartTime = DateTime.Now;
            this.EndTime = DateTime.Now;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="total">任务数量</param>
        /// <param name="qsNumber">采集当前期数</param>
        public CollectStateInfo(int total, string qsNumber, int completed) :this()
        {
            this.TotalRecords = total;
            this.YearQSNumber = qsNumber;
            this.CompletedRecord = completed;
        }

    }

上面的对象,主要用来记录任务的总数,以及当前进行的数量,还包括一些其他信息,如任务的开始时间,结束时间等等,我们可以把一些常规的任务信息,放到这里面来传递即可。

另一个后台进程处理的关键事件就是处理过程的代码实现,主要就是采集处理的逻辑内容,如下所示。

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            CollectStateInfo info = e.Argument as CollectStateInfo;
            if (info != null)
            {
                LinkJob job = new LinkJob();
                var stateInfo = job.Execute(this.worker, info);
                e.Result = stateInfo;
            }
        }

这个里面我么主要到它的e.Argument 就是我们传递的对象,通过类型转换我们就可以获得对应的信息,然后进行具体的处理了。

另外一个就是当整个后台进程完成处理后,我们需要进行相关的提示和状态处理,实现代码如下所示。

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //还原按钮状态
            InitCollectState();
            IsThreadRunning = false;

            string message = "采集操作完成";
            CollectStateInfo stateInfo = e.Result as CollectStateInfo;
            if (stateInfo != null && stateInfo.CompletedRecord == stateInfo.TotalRecords)
            {
                message += string.Format(",完成采集网址{0}个,耗时为:{1}分钟{2}秒。", stateInfo.TotalRecords, stateInfo.TimeSpanUsed.Minutes, stateInfo.TimeSpanUsed.Seconds);

                //清空数据即可
                JobParameterHelper.ClearData();
            }
            else
            {
                message += string.Format(",用户取消处理,耗时为:{1}分钟{2}秒。", stateInfo.TotalRecords, stateInfo.TimeSpanUsed.Minutes, stateInfo.TimeSpanUsed.Seconds);
            }
            MessageDxUtil.ShowTips(message);
        }

而我们开始任务,则通过按钮触发后台线程的异步接口调用即可,如下代码所示。

                if (!worker.IsBusy)
                {
                    this.btnStartCollect.ImageOptions.Image = Resources.Button_Stop;
                    this.lblTips.Text = "数据采集中....,单击按钮可停止采集";
                    this.btnStartCollect.Text = "停止采集";

                    var totalCount = BLLFactory<URLLink>.Instance.GetRecordCount();//数量为总数
                    var stateInfo = new CollectStateInfo(totalCount, yearQSNumber, skipCount);

                    worker.RunWorkerAsync(stateInfo);
                    //改变状态
                    IsThreadRunning = !IsThreadRunning;
                }

这里面我们设置提示开始采集数据后,然后构建一个可以用于传递的线程采集对象给后台线程,通过异步调用worker.RunWorkerAsync(stateInfo); 即可实现任务的开始操作。

如果任务总之,我们调用取消接口即可。

                if (MessageDxUtil.ShowYesNoAndWarning("采集正在进行中,您确认停止采集吗?") == System.Windows.Forms.DialogResult.Yes)
                {
                    worker.CancelAsync();

                    //改变状态
                    IsThreadRunning = !IsThreadRunning;

                    //还原按钮状态
                    InitCollectState();
                }

启动采集界面进行相应的处理即可,如下所示。

采集过程的进度可以通过状态栏实时的显示出来,这个有赖于我们定义的状态类,可以很方便进行UI的信息通知。

以上就是使用后台 线程BackgroundWorker处理任务的一些总结,希望给读者带来一些参考价值,在我们做一些耗时的操作的时候,可以考虑使用这个后台线程BackgroundWorker处理任务,从而实现较好的界面通知,也不会造成UI界面的停顿卡死状态。

 

当前文章:http://mabebox.com/play/bxf7h4kcjg.html

发布时间:2018-11-16 00:00:00

手机最赚钱平台 炒股赚钱绝招 乐赚炒股官网 赚宝网怎么样 秒赚平台怎么样 电脑在家玩游戏就重启 如何在家学画画 汇民投资有限公司

编辑:密伯


声明:所发布的内容均来源于互联网,目的在于传递信息,但不代表本站赞同其观点及立场,版权归属原作者,如有侵权请联系删除。
网赚做什么赚钱

农村家庭创业致富项目

做问卷赚钱