您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

BackgroundWorker的包装器

寒冰屋 发布时间:2020-02-23 19:16:25 ,浏览量:0

目录

介绍

背景

使用代码

兴趣点

有许多使用BackgroundWorker的方法:lambda、匿名委托和事件。所有这些都有优点和缺点,但我发现它们可读性较差。在这里,您将看到使用BackgroundWorker的另一种方法。

介绍

本技巧的目的是展示一种替代的使用BackgroundWorker方法。

背景

Microsoft文档显示了如何与事件一起使用BackgroundWorker,在这些示例中,可以使用其他方法。

BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(
    () =>
    {
       // Do Something
    }
);
bgw.DoWork += (sender, e) => { ... }

bgw.DoWork += delegate { ... }

我发现这些方法不太容易理解,因此建议在下一章中使用该方法。

使用代码
public class PatientMan
    {
        private Action _DoWork = null;
        private Boolean _IsDoWorkSubscribe = false;
        private DoWorkEventHandler _DoWorkHandler;

        private Action _RunWorkerCompleted = null;
        private Boolean _IsRunWorkerCompletedSubscribe = false;
        private RunWorkerCompletedEventHandler _RunWorkerCompletedHandler;

        private Action _ProgressChanged = null;
        private Boolean _IsProgressChangedSubscribe = false;
        private ProgressChangedEventHandler _ProgressChangedHandler;

        private BackgroundWorker _Worker = new BackgroundWorker();

        public PatientMan()
        {

        }

        public PatientMan(Action doWorkAction,
                            Action runWorkerCompleted)
        {
            this.SubcribeDoWork(doWorkAction);
            this.SubcribeRunWorkerCompleted(runWorkerCompleted);
        }

        private void SubcribeDoWork(Action doWorkAction)
        {
            this._DoWork = doWorkAction;
            this._DoWorkHandler = delegate { this._DoWork(); };
            this._Worker.DoWork += _DoWorkHandler;
            this._IsDoWorkSubscribe = true;
        }

        private void SubcribeRunWorkerCompleted(Action runWorkerCompleted)
        {
            this._RunWorkerCompleted = runWorkerCompleted;
            this._RunWorkerCompletedHandler
                =
            delegate {
                this._RunWorkerCompleted();
                this.UnsubscribeEvents();
            };
            this._Worker.RunWorkerCompleted += this._RunWorkerCompletedHandler;
            this._IsRunWorkerCompletedSubscribe = true;
        }

        private void SubcribeProgressChanged(Action progressChanged)
        {
            this._ProgressChanged = progressChanged;
            this._ProgressChangedHandler = (obj, ev) =>
            {
                this._ProgressChanged(ev.ProgressPercentage);
            };
            this._Worker.ProgressChanged += this._ProgressChangedHandler;
            this._Worker.WorkerReportsProgress = true;
            this._IsProgressChangedSubscribe = true;
        }


        public void RunWorkerAsync()
        {
            this._Worker.RunWorkerAsync();
        }


        public  void ReportProgress(int percentage)
        {
            if(this._ProgressChanged != null)
            {
                if (this._IsProgressChangedSubscribe == true)
                {
                    this._Worker.ReportProgress(percentage);
                }
                else
                {
                    throw new ArgumentNullException();
                }
            }
            else
            {
                throw new NullReferenceException();
            }
        }

        private void UnsubscribeEvents()
        {
            if (this._IsDoWorkSubscribe == true)
            {
                this._Worker.DoWork -= this._DoWorkHandler;
                this._IsDoWorkSubscribe = false;
            }

            if (this._IsRunWorkerCompletedSubscribe == true)
            {
                this._Worker.RunWorkerCompleted -= this._RunWorkerCompletedHandler;
                this._IsRunWorkerCompletedSubscribe = false;
            }

            if (this._IsProgressChangedSubscribe == true)
            {
                this._Worker.ProgressChanged -=  this._ProgressChangedHandler;
                this._Worker.WorkerReportsProgress = false;
                this._IsProgressChangedSubscribe = false;
            }
        }

        public void Dispose()
        {
            this.UnsubscribeEvents();
            this._Worker.Dispose();
        }

        public void SetEvents(Action doWorkAction,
                            Action runWorkerCompleted,
                            Action progressChanged,
                            Boolean unsubscribeEvents = false)
        {
            this.UnsubscribeEvents();

            this.SubcribeDoWork(doWorkAction);
            this.SubcribeRunWorkerCompleted(runWorkerCompleted);
            this.SubcribeProgressChanged(progressChanged);
        }
    }

PatientMan类提供了包装BackgroundWorker的基本功能。

可以通过以下方式使用它:

public class SandBoxPatientMan
    {
        public SandBoxPatientMan(int algo)
        {

            switch(algo)
            {
                case 0:
                    {
                        Action doWork = delegate
                        {
                            // Do something long
                            for (int i = 0; i < 10; i++)
                            {
                                System.Threading.Thread.Sleep(1000);
                            }
                        };

                        Action runWorkerCompleted = delegate
                        {
                            // Do something after you did something long

                            Console.WriteLine("runWorkerCompleted " + algo);
                        };

                        PatientMan patientMan = new PatientMan(doWork, runWorkerCompleted);

                        patientMan.RunWorkerAsync();
                    }
                    break;

                case 1:
                    {
                        PatientMan patientMan = new PatientMan();

                        Action doWork = delegate
                        {
                            // Do something long

                            for (int i = 0; i < 10; i++)
                            {
                                System.Threading.Thread.Sleep(1000);

                                patientMan.ReportProgress(i);
                            }
                        };

                        Action runWorkerCompleted = delegate
                        {
                            // Do something after you did something long

                            Console.WriteLine("runWorkerCompleted " + algo);
                        };

                        Action progressChanged = (percentage) =>
                        {
                            // Report a progress during a long process

                            Console.WriteLine("progressChanged " + percentage);
                        };

                        patientMan.SetEvents(doWork, runWorkerCompleted, progressChanged);

                        patientMan.RunWorkerAsync();
                    }
                    break;
            }



        }
    }

通过参数传递委托更加可读和简洁。

以我的经验,它也更容易调试。

兴趣点

此类不能替代完全的BackgroundWorker,它需要一些更新如Cancellation或诸IsBusy。

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0481s