当前位置:网站首页>如何使用Async-Awati异步任務處理代替BackgroundWorker?
如何使用Async-Awati异步任務處理代替BackgroundWorker?
2022-07-04 19:28:00 【界面開發小八哥】
在WinForm開發中有時候我們為了不影響主UI線程的處理,以前我們使用後臺線程BackgroundWorker來處理一些任務操作,不過隨著异步處理提供的便利性,我們可以使用Async-Awati异步任務處理替換原來的後臺線程BackgroundWorker處理方式,更加的簡潔明了。
在一些耗時的操作過程中,在長時間運行時可能會導致用戶界面 (UI) 處於停止響應狀態,因此使用使用Async-Awati异步任務處理或者後臺線程BackgroundWorker來處理一些任務操作很有必要。
在使用BackgroundWorker的過程中,我們可以定義自己的狀態參數信息,從而實現線程狀態的實時跟踪以及進度和信息提示,方便我們及時通知UI進行更新。
現在使用Async-Awati异步任務處理,一樣可以在處理過程中通知UI更新進度和提示信息。
點擊獲取DevExpress Winformv21.2正式版
1. 回顧BackgroundWorker後臺線程的處理代碼
我們先來了解一下BackgroundWorker後臺線程的操作代碼,對比下再介紹使用Async-Awati异步任務處理和通知操作。
一般的使用代碼是需要初始化後臺線程對象的,如下代碼所示。
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));
}
}
後臺進程處理的關鍵事件就是處理過程的代碼實現,它處理任務的時候,把當前的狀態通過事件方式通知UI顯示。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
Random r = new Random();
int numCount = 0;
while (worker.CancellationPending == false)
{
int num = r.Next(0, 10000);
if (num % 5 == 0)
{
numCount++;
worker.ReportProgress(0, num);
Thread.Sleep(1000);
}
}
e.Result = numCount;
}
觸發任務開始的時候,我們調用代碼如下所示。
if (!worker.IsBusy)
{
worker.RunWorkerAsync(stateInfo);
}
任務完成後,通知更新界面即可。
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//還原按鈕狀態
InitCollectState();
IsThreadRunning = false;
string message = "采集操作完成";
MessageDxUtil.ShowTips(message);
}
2. 使用Async-Awati异步任務處理代替BackgroundWorker
為了測試使用Asyn-Await异步處理,我創建一個簡單的Demo程序,用於測試其效果。
窗體裏面放置一個按鈕,觸發按鈕執行任務操作,並逐步提示進度條信息,完成後提示任務完成。
為了在异步處理中提示進度信息,我們引入了Progress 線程通知對象。
定義一個線程通知的Progress對象,如下所示。這裏的int也可以換為自定義的對象類,以方便承載更多的信息。
var reporter = new Progress<int>(progressChanged);
其中progressChanged 是我們定義的一個通知UI顯示進度的處理函數,如下所示。
/// <summary>
/// 報告進度
/// </summary>
/// <param name="percentage">當前進度</param>
void progressChanged(int percentage)
{
this.progressBar1.EditValue = percentage;
this.progressPanel.Caption = percentage == 100 ? "任務已完成": "任務正在處理";
this.progressPanel.Description = String.Format("完成【{0}%】", percentage);
}
接著我們定義一個處理任務的WorkStart方法,接收一個Progress對象,如下代碼所示。
var reporter = new Progress<int>(progressChanged);
var result = await this.WorkStart(reporter);
為了簡單樣式异步調用,我們這裏只是延遲了一下處理任務,實際處理的話,調用异步方法即可。
/// <summary>
/// 執行任務
/// </summary>
private async Task<CommonResult> WorkStart(IProgress<int> progress)
{
var result = new CommonResult();
for(int i = 0; i < 100; i++)
{
await Task.Delay(100);
progress.Report(i + 1);
}
result.Success = true;
return result;
}
我們可以看到,任務每次執行到一個節點,就會調用對象方法Report進行通知處理。
而任務完成後,我們簡單的通知處理即可。整段代碼如下所示。
/// <summary>
/// Async Await异步線程處理
/// </summary>
public partial class FrmAsyncAwaitDemo : DevExpress.XtraEditors.XtraForm
{
public FrmAsyncAwaitDemo()
{
InitializeComponent();
this.progressBar1.Visible = false;
this.progressPanel.Visible = false;
}
private async void btnStart_Click(object sender, EventArgs e)
{
this.btnStart.Enabled = false;
this.progressBar1.Visible = true;
this.progressPanel.Visible = true;
var reporter = new Progress<int>(progressChanged);
var result = await this.WorkStart(reporter);
this.WorkCompleted(result);
}
/// <summary>
/// 任務完成
/// </summary>
/// <param name="result">返回結果CommonResult</param>
void WorkCompleted(CommonResult result)
{
if (result.Success)
{
//操作成功的處理
}
var alert = new AlertControl();
alert.FormLocation = AlertFormLocation.TopRight;
alert.AutoFormDelay = 2000;
alert.Show(this, "任務提示", result.Success ? "任務處理完成,操作成功" : result.ErrorMessage);
this.progressBar1.Visible = false;
this.progressPanel.Visible = false;
this.btnStart.Enabled = true;
}
/// <summary>
/// 報告進度
/// </summary>
/// <param name="percentage">當前進度</param>
void progressChanged(int percentage)
{
this.progressBar1.EditValue = percentage;
this.progressPanel.Caption = percentage == 100 ? "任務已完成": "任務正在處理";
this.progressPanel.Description = String.Format("完成【{0}%】", percentage);
}
/// <summary>
/// 執行任務
/// </summary>
private async Task<CommonResult> WorkStart(IProgress<int> progress)
{
var result = new CommonResult();
for(int i = 0; i < 100; i++)
{
await Task.Delay(100);
progress.Report(i + 1);
}
result.Success = true;
return result;
}
}
在我們實際的案例中,文件上傳處理就使用了這種方式來通知UI線程,任務處理的代碼如下所示。
因此使用Async-Awati异步任務處理代替BackgroundWorker,代碼更加簡便,而且使用 IProgress接口類來處理通知,也是非常方便的。
DevExpress WinForm擁有180+組件和UI庫,能為Windows Forms平臺創建具有影響力的業務解决方案。DevExpress WinForms能完美構建流暢、美觀且易於使用的應用程序,無論是Office風格的界面,還是分析處理大批量的業務數據,它都能輕松勝任!
本文轉載自:博客園 - 伍華聰
DevExpress技術交流群6:600715373 歡迎一起進群討論
边栏推荐
- 876. 链表的中间结点
- 小发猫物联网平台搭建与应用模型
- MySQL数据库基本操作-DDL | 黑马程序员
- Oracle with as ORA-00903: invalid table name 多表报错
- One question per day (2022-07-02) - Minimum refueling times
- Lm10 cosine wave homeopathic grid strategy
- Unity编辑器扩展C#遍历文件夹以及子目录下的所有图片
- 添加命名空间声明
- Nebula importer data import practice
- 与二值化阈值处理相关的OpenCV函数、方法汇总,便于对比和拿来使用
猜你喜欢
Go microservice (II) - detailed introduction to protobuf
Build your own website (15)
redis分布式锁的8大坑总结梳理
读写关闭的channel是啥后果?
Oracle with as ora-00903: invalid table name multi report error
英特尔集成光电研究最新进展推动共封装光学和光互连技术进步
LM10丨余弦波动顺势网格策略
如何使用Async-Awati异步任务处理代替BackgroundWorker?
正则替换【JS,正则表达式】
在线SQL转Excel(xls/xlsx)工具
随机推荐
Download the first Tencent technology open day course essence!
In flinksql, in addition to data statistics, is the saved data itself a state
模板_大整数减法_无论大小关系
6.26cf simulation race e: solution to the problem of price maximization
基于NCF的多模块协同实例
FPGA时序约束分享01_四大步骤简述
物联网应用技术的就业前景和现状
The 300th weekly match of leetcode (20220703)
Build your own website (15)
Don't just learn Oracle and MySQL!
SSL证书续费相关问题详解
大佬们,求助一下,我用mysql cdc 2.2.1(flink 1.14.5)写入kafka,设置
IBM WebSphere MQ检索邮件
Detailed explanation of issues related to SSL certificate renewal
Lm10 cosine wave homeopathic grid strategy
LeetCode FizzBuzz C#解答
A method of using tree LSTM reinforcement learning for connection sequence selection
技术分享 | 接口测试价值与体系
Rookie post station management system based on C language
2022-07-04: what is the output of the following go language code? A:true; B:false; C: Compilation error. package main import 'fmt' func