这篇文章给大家介绍怎么在C#中使用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的信息通知。
关于怎么在C#中使用BackgroundWorker处理任务就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。