一. 概述
在使用c#進行應用程式設計時,經常會採用多執行緒的方式進行一些後台任務的工作。對於不同的應用場景,使用的策略也不盡相同。
1. 後台迴圈任務,少量ui更新:例如批量上傳檔案,並提供進度。這種情況使用backgroundworker元件是非常好的選擇。
2. 耗時的後台任務:這裡的耗時任務是指乙個時間較長的任務,並且不能精確獲取進度,如:呼叫乙個遠端webservice介面。這種情況可以開兩個執行緒,乙個工作,乙個更新ui(不能提供進度,只能顯示動畫表示系統在執行中)。
3. 耗時的ui任務:當工作壓力集中在ui響應上時,可以在工作者執行緒中增加延時,從而讓ui執行緒獲得響應時間。整個工作的總體時間會增加,但使用者響應效果會好很多。
二. 後台的迴圈任務,少量ui更新
這種情況使用backgroundworker元件是最好的選擇。(詳見附一)
三. 後台耗時任務
在後台執行乙個不可分解的耗時任務,需要進行介面更新,以便讓客戶看上去程式有所響應。這種情況下,ui執行緒一般也不知道工作執行緒何時結束,所以一般執行迴圈任務,當工作執行緒結束後,關閉ui執行緒就可以了。
thread uithread = null;
private void btnstart_click(object sender, eventargs e)
uithread = new thread(new threadstart(this.updateprogressthread));
uithread.start();
thread workthread = new thread(new threadstart(this.dosomething));
workthread.start();
private void dosomething()
thread.sleep(5000);
uithread.abort();
messagebox.show("work end");
private void updateprogressthread()
for (int i = 0; i < 10000; i++)
thread.sleep(100);
this.invoke(new action(this.updateprogress), i);
private void updateprogress(int v)
this.progressbar1.value = v;
這裡只要注意一點:執行緒呼叫的方法都不能訪問使用者控制項,必須通過委託呼叫form的方法來實現介面更新。
四. 耗時的ui任務
當整個工作壓力集中在ui響應上時,可以在工作者執行緒中增加延時,從而讓ui執行緒獲得響應時間。整個工作的總體時間會增加,但使用者響應效果會好很多。
private void forminitform_load(object sender, eventargs e)
this.listview1.items.clear();
thread workthread = new thread(new threadstart(this.dosomething));
workthread.start();
private void dosomething()
for (int i = 0; i < 30; i++)
this.invoke(new action(this.loadpicture), i);
thread.sleep(100);
private void loadpicture(int i)
string text = string.format("item", i);
listviewitem lvi = new listviewitem(text, 0);
this.listview1.items.add(lvi);
thread.sleep(200);//模擬耗時ui任務,非迴圈,不可分解
五. 補充
1. invoke 和 begininvoke
在多執行緒程式設計中,我們經常要在工作執行緒中去更新介面顯示,而在多執行緒中直接呼叫介面控制項的方法是錯誤的做法,正確的做法是將工作執行緒中涉及更新介面的**封裝為乙個方法,通過 invoke 或者 begininvoke 去呼叫,兩者的區別就是乙個導致工作執行緒等待,而另外乙個則不會。
而所謂的「一面響應操作,一面新增節點」永遠只能是相對的,使 ui 執行緒的負擔不至於太大而以,因為介面的正確更新始終要通過 ui 執行緒去做,我們要做的事情是在工作執行緒中包攬大部分的運算,而將對純粹的介面更新放到 ui 執行緒中去做,這樣也就達到了減輕 ui 執行緒負擔的目的了。
private void button2_click(object sender, eventargs e)
for (int i = 0; i < 30; i++)
string text = string.format("item", i);
listviewitem lvi = new listviewitem(text, 0);
this.listview1.items.add(lvi);
thread.sleep(200);
for (int j = 0; j < 10; j++)
thread.sleep(10);
3. lock
lock(object)
等價與try
monitor.enter(object);
finally
monitor.exit(object)
附一:backgroundworker元件使用說明
一. 概述
backgroundworker是·net 2.0提供的乙個多執行緒元件,在應用程式中使用,可以非常簡單方便地實現ui控制項通訊,並自動處理多執行緒衝突問題。
二. 基本屬性
1. workerreportsprogress ,bool:是否允許報告進度;
2. workersupportscancellation,bool:是否允許取消執行緒。
3. cancellationpending,bool,get:讀取使用者是否取消該執行緒。
三. 基本事件
1. dowork:工作者執行緒
2. runworkercompleted :執行緒進度報告
3. progresschanged:執行緒結束報告
四. 基本方法
1. runworkerasync() :啟動工作者執行緒;
2. cancelasync():取消工作者執行緒;
3. reportprogress(int); 報告進度
五. **
//啟動
private void btnstart_click(object sender, eventargs e)
this.btnstart.enabled = false;
this.btnstop.enabled = true;
this.backgroundworker.runworkerasync();
//通知執行緒停止
private void btnstop_click(object sender, eventargs e)
this.backgroundworker.cancelasync();
//工作者執行緒
private void backgroundworker_dowork(object sender, doworkeventargs e)
for (int i = 0; i < 150; i++)
if (backgroundworker.cancellationpending) //檢視使用者是否取消該執行緒
break;
system.threading.thread.sleep(50); //幹點實際的事
backgroundworker.reportprogress(i); //報告進度
//執行緒進度報告
private void backgroundworker_progresschanged(object sender, progresschangedeventargs e)
this.progressbar1.value = e.progresspercentage * 100 / 150;
//執行緒結束報告
private void backgroundworker_runworkercompleted(object sender, runworkercompletedeventargs e)
this.btnstart.enabled = true;
this.btnstop.enabled = false;
C 多執行緒與UI響應
一 概述 在使用c 進行應用程式設計時,經常會採用多執行緒的方式進行一些後台任務的工作。對於不同的應用場景,使用的策略也不盡相同。1.後台迴圈任務,少量ui更新 例如批量上傳檔案,並提供進度。這種情況使用backgroundworker元件是非常好的選擇。2.耗時的後台任務 這裡的耗時任務是指乙個時...
C 多執行緒與UI響應
一 概述 在使用c 進行應用程式設計時,經常會採用多執行緒的方式進行一些後台任務的工作。對於不同的應用場景,使用的策略也不盡相同。1.後台迴圈任務,少量ui更新 例如批量上傳檔案,並提供進度。這種情況使用backgroundworker元件是非常好的選擇。2.耗時的後台任務 這裡的耗時任務是指乙個時...
C 多執行緒與UI響應
一 概述 在使用c 進行應用程式設計時,經常會採用多執行緒的方式進行一些後台任務的工作。對於不同的應用場景,使用的策略也不盡相同。1.後台迴圈任務,少量ui更新 例如批量上傳檔案,並提供進度。這種情況使用backgroundworker元件是非常好的選擇。2.耗時的後台任務 這裡的耗時任務是指乙個時...