博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#线程运行的机制和原理
阅读量:7095 次
发布时间:2019-06-28

本文共 6226 字,大约阅读时间需要 20 分钟。

hot3.png

BackgroundWorker类可以简化线程在后台执行任务的工作,它具有以下几种主要成员:

属性:WorkReportsProgress,WorkerSupportsCancellation,IsBusy;方法: RunWorkerAsync( ),CancellAsync( ),ReportProgress( );事件:DoWork,ProgressChanged,RunWorkerCompleted;这几种主要成员。

WorkReportsProgress以及WorkerSupportsCancellation属性用于设置是否后台任务可以把进度汇报给主线程以及是否支持从主线程取消;IsBusy属性用来检查是否正在运行后台任务。 3种事件用于发送不同的程序事件和状态;后台线程开始时触发Dowork事件,后台任务汇报状态的时候触发ProgressChanged事件,后台工作线程退出的时候触发RunWorkerCompleted事件。 3种方法用于初始化行为或改变状态;调用RunWorkerAsync方法获取后台线程并且执行DoWork事件处理程序;调用CancelAsync方法把CancellationPending属性设置为True,虽不是必要的,但潜在的取消了线程,DoWork事件处理程序需要检查这个属性来决定是否应该停止处理;DoWork事件处理程序,在后台线程中如果希望向主线程汇报进度时,调用ReportProgress方法。

这些事件处理程序的委托如下:每一个任务都有一个Object对象的引用作为第一个参数,以及EventArgs类的特定子类作为第二个参数                        void DoWorkEventHandler (object sender, DoWorkEventArgs e)                        void ProgressChangeEventHandler(object sender, ProgressChangeEventArgs e)                  void RunWorkerCompletedEventHandler(object sender, RunWorkerCompletedEventArgs e)

当为这些事件写附加事件处理程序时,应该如下来使用这些类。

从创建BackgroundWorker类的对象并对它进行配置开始,如果希望工作线程为主线程汇报进度,需要把WorkReportsProgress属性设置为ture;如果希望从主线程取消工作线程,就把WorkerSupportsCancellation属性设置为true。  设置好属性后,就可以通过调用RunWorkerAsync方法来启动它,它会开一个后台线程并发起DoWork事件处理后台程序。  在主线程中,如果你已启用了WorkerSupportsCancellation属性,然后可以调用CancelAsync方法,它会设置CancellationPending的属性为true,我们需要在后台线程DoWork事件处理代码中检测这个属性。

在后台线程继续执行任务时,要做以下几件事情: 如果WorkReportsProgress属性为true并且后台线程要为主程序汇报进度的话,必须调用BackgroundWorker对象的ReportProgress方法,这时会触发主线程的ProgressChanged事件,从而运行相应的事件处理程序。 如果WorkerSupportsCancellation属性为true,DoWork事件处理代码应该时时检测CancellationPending属性来确定是否已经取消,若是的话应该退出后台线程。 如果后台线程没有取消,完成了其处理程序,则可以通过设置DoWorkEventArgs参数的Result字段来返回结果给主线程。

在后台线程退出的时候会触发RunWorkerCompleted事件,其事件处理程序会在主线程上执行。RunWorkerCompletedEventArgs参数可以包含已完成后台线程的一些信息,比如返回值以及线程是否被取消了。 如下是代码实现:

using System;using System.Collections.Generic;using System.Threading;using System.Linq;using System.Text;using System.ComponentModel;//线程实现原理namespace ConsoleApplication2{    class DoBackgroundwork    {        BackgroundWorker bgWorker = new BackgroundWorker();        public long BackgroundTotal {get; private set;}        public bool CompletedNormally {get; private set;}                //构造方法        public DoBackgroundwork()        {            //设置BackgroundWorker属性            bgWorker.WorkerReportsProgress = true;            bgWorker.WorkerSupportsCancellation = true;            //把处理程序连接到BackgroundWorker对象            bgWorker.DoWork += DoWork_Handler;            bgWorker.ProgressChanged += ProgressChanged_Handler;            bgWorker.RunWorkerCompleted += RunWorkerCompleted_Handler;        }        public void StartWorker()        {            if(!bgWorker.IsBusy)            {                bgWorker.RunWorkerAsync();            }        }        、、        public static long CalculateTheSequence(long value)        {            long total = 0;            for(int i = 0; i < value; ++i)            {                total += i;            }            return total;        }        public void DoWork_Handler(object sender, DoWorkEventArgs args)        {            BackgroundWorker worker = sender as BackgroundWorker;            long total = 0;            for(int i = 0; i <= 5; ++i)            {                if(worker.CancellationPending)                {                    args.Cancel = true;                    worker.ReportProgress(-1);                    break;                }                else                {                    total += CalculateTheSequence(i * 10000000);                    worker.ReportProgress(i * 20);                    Thread.Sleep(300);                }            }            args.Result = total;        }        private void ProgressChanged_Handler(object sender, ProgressChangedEventArgs args)        {            string output = args.ProgressPercentage == -1                ? "   Cancelled"                : string.Format("               {0}%", args.ProgressPercentage);            System.Console.WriteLine(output);        }        private void RunWorkerCompleted_Handler(object sender, RunWorkerCompletedEventArgs args)        {            CompletedNormally = !args.Cancelled;            BackgroundTotal = args.Cancelled ? 0 : (long)args.Result;        }        public void Cancel()        {            if(bgWorker.IsBusy)            {                bgWorker.CancelAsync();            }        }    }    class Program    {        static void Main(string[] args)        {            GiveInstructionsToTheUser();            OutputTheSummaryHeaders();            DoBackgroundwork bgw = new DoBackgroundwork();            bgw.StartWorker();            long mainTotal = 0;            for (int i = 0; i < 5; ++i)            {                if (Program.CheckForCancelInput())                {                    bgw.Cancel();                }                mainTotal += DoBackgroundwork.CalculateTheSequence(100000000);                Thread.Sleep(200);                System.Console.WriteLine("     {0}%", (i + 1) * 20);            }            SummarizeResults(bgw, mainTotal);            System.Console.ReadLine();        }        private static void GiveInstructionsToTheUser()        {            System.Console.WriteLine("Press 
to start."); System.Console.ReadLine(); } private static void OutputTheSummaryHeaders() { System.Console.WriteLine(" Main Background "); System.Console.WriteLine("---------------------"); } private static void SummarizeResults(DoBackgroundwork bgw, long mainTotal) { if (bgw.CompletedNormally) { System.Console.WriteLine("\nBackground Completed Normally"); System.Console.WriteLine("Background Total = {0}.", bgw.BackgroundTotal); } else { System.Console.WriteLine("\nBackground Cancelled."); } System.Console.WriteLine("Main Total ={0}.", mainTotal); } private static bool CheckForCancelInput() { bool doCancel = Console.KeyAvailable; if (doCancel) { Console.ReadKey(); } return doCancel; } }}

运行结果如下: 输入图片说明

转载于:https://my.oschina.net/u/1032782/blog/794876

你可能感兴趣的文章
浅谈物联网所面对的问题和挑衅
查看>>
期刊发表要求都有哪些
查看>>
php导出数据到excel,身份证等数字常用格式
查看>>
我的友情链接
查看>>
Grub 配置解析(1)
查看>>
Oracle数据库管理常用的监控脚本------极大的简化运维工作
查看>>
Oracle10g之SGA与PGA分配建议
查看>>
骆驼命名发
查看>>
我的友情链接
查看>>
liunx服务使用(mysql数据库的安装和传说中的LAMP的安装【论坛的搭建】)
查看>>
码农,你真的准备好转产品了吗?
查看>>
TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
查看>>
LOVEFiLM Cashback
查看>>
shell-scripts,FTP自动化上传脚本,可循环,直到上传成功为止
查看>>
使用shell脚本实现加法乘法运算
查看>>
jQuery插件开发1:分页条
查看>>
pycharm调试edx环境搭建
查看>>
11.10/11.11/11.12 安装PHP5 11.13 安装PHP7
查看>>
HQL:实用技术
查看>>
css基本使用
查看>>