• PDA开发系列:BackgroundWorker


         在.net compact framework中,没有BackgroundWorker,应该会让我们这些用惯了BackgroundWorker的人感到非常的不便。BackgroundWorker可以非常方便解决线程和控件之间的互操作问题,做出界面运行非常流畅的引用程序。(该组件因wince的某些特性,不能解决根本问题,建议还是用线程来解决。)

        在反编译了.net framework的BackgroundWorker后,发现基本上95%以上的代码都可以直接COPY过来,唯一存在问题的就是下面这段代码:

            if (this.asyncOperation != null)
            {
                this.asyncOperation.Post(this.progressReporter, arg);
            }
            else
            {
                this.progressReporter(arg);
            }
    
    这段代实际上要做的事情是这样的:如果执行该方法的线程和控件所在的线程不是同一个线程,就把该委托交给控件所在的线程去执行,否则就直接执行,为了实现这个操作,我做了如下的改动,在构造函数中,我这样写:

    public BackgroundWorker()
    {
        this.threadStart = new WorkerThreadStartDelegate(this.WorkerThreadStart);
        this.operationCompleted = new SendOrPostCallback(this.AsyncOperationCompleted);
        this.progressReporter = new SendOrPostCallback(this.ProgressReporter);
        this.Handler = Thread.CurrentThread.ManagedThreadId;
    }

    所以,上面的代码我做了如下的改写:

    if (Thread.CurrentThread.ManagedThreadId!= this.Handler)
    {
        Post(this.progressReporter, arg);
    }
    else
    {
        this.progressReporter(arg);
    }

    Post方法的代码如下:

    public virtual void Post(SendOrPostCallback d, object state)
    {
        if (d != null && controlToSendTo != null)
        {
            controlToSendTo.Invoke(d, state);
        }
    }

    controlToSendTo 是调用该BackgroundWorker得用户控件。该BackgroundWorker得所有代码是这样的:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace ZFB.PDA.Dao
    {
        public class BackgroundWorker : Component
        {
            private bool canCancelWorker;
            private bool cancellationPending;
            private static readonly object doWorkKey = new object();
            private bool isRunning;
            private readonly SendOrPostCallback operationCompleted;
            private static readonly object progressChangedKey = new object();
            private readonly SendOrPostCallback progressReporter;
            private static readonly object runWorkerCompletedKey = new object();
            private readonly WorkerThreadStartDelegate threadStart;
            private readonly int Handler = 0;
            private Control controlToSendTo = null;
    
    
            /// <summary>
            /// 开始后台任务
            /// </summary>
            public event DoWorkEventHandler DoWork
            {
                add
                {
                    base.Events.AddHandler(doWorkKey, value);
                }
                remove
                {
                    base.Events.RemoveHandler(doWorkKey, value);
                }
            }
    
            /// <summary>
            /// 后台任务执行的进度
            /// </summary>
            public event ProgressChangedEventHandler ProgressChanged
            {
                add
                {
                    base.Events.AddHandler(progressChangedKey, value);
                }
                remove
                {
                    base.Events.RemoveHandler(progressChangedKey, value);
                }
            }
    
            /// <summary>
            /// 后台任务完成
            /// </summary>
            public event RunWorkerCompletedEventHandler RunWorkerCompleted
            {
                add
                {
                    base.Events.AddHandler(runWorkerCompletedKey, value);
                }
                remove
                {
                    base.Events.RemoveHandler(runWorkerCompletedKey, value);
                }
            }
    
            public BackgroundWorker()
            {
                this.threadStart = new WorkerThreadStartDelegate(this.WorkerThreadStart);
                this.operationCompleted = new SendOrPostCallback(this.AsyncOperationCompleted);
                this.progressReporter = new SendOrPostCallback(this.ProgressReporter);
                this.Handler = Thread.CurrentThread.ManagedThreadId;
            }
    
            private void AsyncOperationCompleted(object arg)
            {
                this.isRunning = false;
                this.cancellationPending = false;
                this.OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg);
            }
    
            public void CancelAsync()
            {
                this.cancellationPending = true;
            }
    
            protected virtual void OnDoWork(DoWorkEventArgs e)
            {
                DoWorkEventHandler handler = (DoWorkEventHandler)base.Events[doWorkKey];
                if (handler != null)
                {
                    handler(this, e);
                }
            }
    
            protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
            {
                ProgressChangedEventHandler handler = (ProgressChangedEventHandler)base.Events[progressChangedKey];
                if (handler != null)
                {
                    handler(this, e);
                }
            }
    
            protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
            {
                RunWorkerCompletedEventHandler handler = (RunWorkerCompletedEventHandler)base.Events[runWorkerCompletedKey];
                if (handler != null)
                {
                    handler(this, e);
                }
            }
    
            private void ProgressReporter(object arg)
            {
                this.OnProgressChanged((ProgressChangedEventArgs)arg);
            }
    
            public void ReportProgress(int percentProgress)
            {
                this.ReportProgress(percentProgress, null);
            }
    
            public void ReportProgress(int percentProgress, object userState)
            {
                ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
                if (Thread.CurrentThread.ManagedThreadId!= this.Handler)
                {
                    Post(this.progressReporter, arg);
                }
                else
                {
                    this.progressReporter(arg);
                }
            }
    
            public void RunWorkerAsync(Control ctl)
            {
                this.RunWorkerAsync(ctl,null);
            }
    
            public void RunWorkerAsync(Control ctl,object argument)
            {
                if (this.isRunning)
                {
                    throw new InvalidOperationException("BackgroundWorker_WorkerAlreadyRunning");
                }
                if (ctl == null)
                {
                    throw new Exception();
                }
                controlToSendTo = ctl;
                this.isRunning = true;
                this.cancellationPending = false;
                this.threadStart.Invoke(argument);
            }
    
            private void WorkerThreadStart(object argument)
            {
                object result = null;
                Exception error = null;
                bool cancelled = false;
                try
                {
                    DoWorkEventArgs e = new DoWorkEventArgs(argument);
                    this.OnDoWork(e);
                    if (e.Cancel)
                    {
                        cancelled = true;
                    }
                    else
                    {
                        result = e.Result;
                    }
                }
                catch (Exception exception2)
                {
                    error = exception2;
                }
                RunWorkerCompletedEventArgs arg = new RunWorkerCompletedEventArgs(result, error, cancelled);
                if (Thread.CurrentThread.ManagedThreadId != this.Handler)
                {
                    Post(this.operationCompleted, arg);
                }
                else
                {
                    this.operationCompleted(arg);
                }
            }
    
            public bool CancellationPending
            {
                get
                {
                    return this.cancellationPending;
                }
            }
    
            public bool IsBusy
            {
                get
                {
                    return this.isRunning;
                }
            }
    
            public bool WorkerSupportsCancellation
            {
                get
                {
                    return this.canCancelWorker;
                }
                set
                {
                    this.canCancelWorker = value;
                }
            }
    
            public virtual void Post(SendOrPostCallback d, object state)
            {
                if (d != null && controlToSendTo != null)
                {
                    controlToSendTo.Invoke(d, state);
                }
            }
    
            private delegate void WorkerThreadStartDelegate(object argument);
            public delegate void SendOrPostCallback(object state);
        }
    
    }

        如果大家有更好的办法,希望大家给我留言。。。

    代码下载:BackgroundWorker

    作者:HOH
    出处:http://hoh.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    大端小端
    浅谈协程
    boost总结之any
    boost总结之variant
    STL总结之functor
    zabbix设置多个收件人
    zabbix设置发送消息的时间
    zabbix利用微信报警
    Windos无法验证文件数组签名
    zabbix基础安装
  • 原文地址:https://www.cnblogs.com/HOH/p/1862932.html
Copyright © 2020-2023  润新知