BackgroundWorker的包装器

目录

介绍

背景

使用代码

兴趣点


有许多使用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<int> _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<int> 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<int> 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<int> progressChanged = (percentage) =>
                        {
                            // Report a progress during a long process

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

                        patientMan.SetEvents(doWork, runWorkerCompleted, progressChanged);

                        patientMan.RunWorkerAsync();
                    }
                    break;
            }



        }
    }

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

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

兴趣点

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

BackgroundWorker是一个用于执行异步操作的类。当调用BackgroundWorker.RunWorkerAsync()方法时,会触发DoWork事件,该事件用于执行耗时的操作。需要注意的是,DoWork事件内部的代码运行在非UI线程上,所以应避免在该事件内部与用户界面进行交互。与用户界面交互的操作应放置在ProgressChanged和RunWorkerCompleted事件中。\[1\]\[2\] 另外,BackgroundWorker还提供了ReportProgress方法,用于在执行异步操作的过程中报告进度。当调用BackgroundWorker.ReportProgress(int percentProgress)方法时,会触发ProgressChanged事件。该事件的ProgressChangedEventArgs.ProgressPercentage属性可以接收来自ReportProgress方法传递的percentProgress参数值,而ProgressChangedEventArgs.UserState属性可以接收来自ReportProgress方法传递的userState参数。\[3\] 总之,BackgroundWorker是一个方便的工具,可以帮助我们在后台执行耗时的操作,同时保持用户界面的响应性。 #### 引用[.reference_title] - *1* *3* [BackgroundWorker使用总结](https://blog.csdn.net/CodeRookieGuo/article/details/72723310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C#多线程之BackgroundWorker](https://blog.csdn.net/sinat_31608641/article/details/106116204)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值