C# winfrom異步加載數(shù)據(jù)不影響窗體UI的操作方法
前言
在數(shù)字浪潮洶涌澎湃的時(shí)代,程序開(kāi)發(fā)宛如一座神秘而宏偉的魔法城堡,矗立在科技的浩瀚星空中。代碼的字符,似那閃爍的星辰,按照特定的軌跡與節(jié)奏,組合、交織、碰撞,即將開(kāi)啟一場(chǎng)奇妙且充滿無(wú)限可能的創(chuàng)造之旅。當(dāng)空白的文檔界面如同深邃的宇宙等待探索,程序員們則化身無(wú)畏的星辰開(kāi)拓者,指尖在鍵盤上輕舞,準(zhǔn)備用智慧與邏輯編織出足以改變世界運(yùn)行規(guī)則的程序畫(huà)卷,在 0 和 1 的二進(jìn)制世界里,鐫刻下屬于人類創(chuàng)新與突破的不朽印記。
一、背景介紹
在 WinForms 應(yīng)用程序中,如果數(shù)據(jù)加載是一個(gè)比較耗時(shí)的操作(比如從數(shù)據(jù)庫(kù)讀取大量數(shù)據(jù)、加載大型文件等),直接在主線程中進(jìn)行加載會(huì)導(dǎo)致 UI 凍結(jié)。這是因?yàn)?WinForms 的 UI 是單線程的,主線程被阻塞時(shí)就無(wú)法處理其他 UI 相關(guān)的任務(wù),如用戶輸入、界面更新等。而異步加載數(shù)據(jù)可以解決這個(gè)問(wèn)題,讓數(shù)據(jù)加載在后臺(tái)線程進(jìn)行,UI 線程可以繼續(xù)響應(yīng)用戶操作。
二、使用BackgroundWorker組件實(shí)現(xiàn)異步加載數(shù)據(jù)
2.1 添加BackgroundWorker組件
添加BackgroundWorker組件:在 WinForms 設(shè)計(jì)器中,從工具箱的 “組件” 選項(xiàng)卡中找到 “BackgroundWorker” 并將其拖放到窗體上。
2.2 處理DoWork事件
處理DoWork事件:這個(gè)事件在后臺(tái)線程中執(zhí)行,用于加載數(shù)據(jù)。例如,如果要從數(shù)據(jù)庫(kù)加載數(shù)據(jù),可以在這個(gè)事件處理程序中編寫數(shù)據(jù)庫(kù)訪問(wèn)代碼。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // 這里模擬一個(gè)耗時(shí)的數(shù)據(jù)加載操作,比如從數(shù)據(jù)庫(kù)讀取數(shù)據(jù) System.Threading.Thread.Sleep(5000); // 假設(shè)這里是真正從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)的代碼 List<string> data = new List<string>(); data.Add("Data 1"); data.Add("Data 2"); // 將加載的數(shù)據(jù)作為結(jié)果返回 e.Result = data; }
處理RunWorkerCompleted事件:當(dāng)后臺(tái)操作完成后,這個(gè)事件會(huì)在主線程中被觸發(fā)。在這里可以更新 UI 來(lái)顯示加載的數(shù)據(jù)。
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error == null) { List<string> data = (List<string>)e.Result; // 假設(shè)dataGridView1是一個(gè)DataGridView控件,用于顯示數(shù)據(jù) dataGridView1.DataSource = data; } else { // 處理錯(cuò)誤情況,比如顯示錯(cuò)誤消息 MessageBox.Show("數(shù)據(jù)加載出錯(cuò):" + e.Error.Message); } }
啟動(dòng)異步操作:可以在某個(gè)按鈕的點(diǎn)擊事件或者窗體的加載事件等地方啟動(dòng)BackgroundWorker。
private void button1_Click(object sender, EventArgs e) { if (!backgroundWorker1.IsBusy) { backgroundWorker1.RunWorkerAsync(); } }
使用async/await實(shí)現(xiàn)異步加載數(shù)據(jù)(如果數(shù)據(jù)加載操作本身支持異步方法)
假設(shè)你有一個(gè)異步方法來(lái)加載數(shù)據(jù),例如從網(wǎng)絡(luò)獲取數(shù)據(jù)的異步方法。
private async void button2_Click(object sender, EventArgs e) { // 假設(shè)LoadDataAsync是一個(gè)異步方法,用于加載數(shù)據(jù) List<string> data = await LoadDataAsync(); dataGridView1.DataSource = data; }
這個(gè)LoadDataAsync方法可能內(nèi)部使用HttpClient從網(wǎng)絡(luò)獲取數(shù)據(jù)等,并且使用async和await關(guān)鍵字來(lái)實(shí)現(xiàn)異步操作。例如:
private async Task<List<string>> LoadDataAsync() { using (HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync("https://example.com/api/data"); if (response.IsSuccessStatusCode) { string json = await response.Content.ReadAsStringAsync(); // 假設(shè)這里是將JSON數(shù)據(jù)反序列化為L(zhǎng)ist<string>的代碼 return JsonConvert.Deserialize<List<string>>(json); } else { throw new Exception("數(shù)據(jù)加載失敗"); } } }
三、延伸內(nèi)容
3.1 錯(cuò)誤處理和進(jìn)度報(bào)告
錯(cuò)誤處理和進(jìn)度報(bào)告:在BackgroundWorker中,可以通過(guò)RunWorkerCompletedEventArgs.Error屬性來(lái)處理錯(cuò)誤,還可以使用BackgroundWorker.ProgressChanged事件來(lái)報(bào)告進(jìn)度。對(duì)于async/await,可以使用try - catch塊來(lái)處理異常,并且如果加載過(guò)程有進(jìn)度信息,可以通過(guò)事件或者返回的進(jìn)度對(duì)象來(lái)更新 UI 顯示進(jìn)度。
3.2 線程安全
線程安全:在更新 UI 時(shí),要確保操作是線程安全的。對(duì)于BackgroundWorker,因?yàn)镽unWorkerCompleted事件是在主線程中觸發(fā)的,所以可以直接更新 UI。但如果是在其他異步場(chǎng)景下,可能需要使用Invoke或BeginInvoke方法來(lái)確保在主線程中更新 UI,以避免跨線程訪問(wèn)異常。
結(jié)束語(yǔ)
以上就是C# winfrom異步加載數(shù)據(jù)不影響窗體UI的操作方法的詳細(xì)內(nèi)容,更多關(guān)于C# winfrom異步加載數(shù)據(jù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#模式畫(huà)刷HatchBrush用法實(shí)例
這篇文章主要介紹了C#模式畫(huà)刷HatchBrush用法,實(shí)例分析了模式畫(huà)刷HatchBrush繪圖的相關(guān)技巧,需要的朋友可以參考下2015-06-06C#實(shí)現(xiàn)發(fā)送簡(jiǎn)單HTTP請(qǐng)求的方法
這篇文章主要介紹了C#實(shí)現(xiàn)發(fā)送簡(jiǎn)單HTTP請(qǐng)求的方法,涉及C#操作http的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04C# 通過(guò)Socket讀取大量數(shù)據(jù)的示例
這篇文章主要介紹了C# 通過(guò)Socket讀取大量數(shù)據(jù)的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03C#實(shí)現(xiàn)對(duì)圖片文件的壓縮、裁剪操作實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)圖片文件的壓縮、裁剪操作,較為詳細(xì)的介紹了操作過(guò)程中用到的相關(guān)類文件及具體的操作步驟,是非常實(shí)用的技巧,需要的朋友可以參考下2014-09-09C#使用DllImport調(diào)用非托管的代碼的方法
C#調(diào)用非托管代碼的方式主要有Com調(diào)用、DllImport方式調(diào)用、加載非托管動(dòng)態(tài)鏈接庫(kù)、直接執(zhí)行機(jī)器碼等方式?,F(xiàn)在介紹一下我自己常用的DllImport方式調(diào)用MSDN中提到的GetShortPathName方法;2013-03-03C#實(shí)現(xiàn)簡(jiǎn)單的loading提示控件實(shí)例代碼
本文通過(guò)實(shí)例代碼給大家介紹了C#實(shí)現(xiàn)簡(jiǎn)單的loading提示控件功能,代碼非常簡(jiǎn)單,具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09