處理WinForm多執行緒程式時的陷阱 摘自網路

2022-04-29 05:15:06 字數 1553 閱讀 7224

與所有的ui開發平台一樣,.net下執行緒開發圖形介面同樣要遵循乙個基本原則:就是對ui物件的操作一定要在產生該ui物件的執行緒裡進行(該執行緒稱作ui執行緒),因為大部分ui物件都不是執行緒安全的。

在.net中,把呼叫呼叫放在ui執行緒裡執行是通過form類及其子類的invoke()方法實現的(具體的過程請參考其他資料),可以這樣做是因為form物件儲存了建立它的執行緒的資訊,而且form類有乙個bool型別的屬性invokerequired,可以通過它檢視當前執行緒是否為建立該form物件的執行緒(ui執行緒)——如果為true,則表示當前執行緒不是ui執行緒,反之則是。下面提供乙個例子:

using

system.threading;

using system.windows.forms;

namespace csharptest

{public

class testform : form

{private form form1;

private form form2;

public static

testform裡有兩個需要注意的方法,uithread——用來模擬ui執行緒,workerthread——用來模擬使用者執行緒,uithread中例項化了成員form1與form2,並呼叫了它們的show方法,在workerthread中改變form1的text屬性。請注意workerthread裡有個技巧, if (form2.invokerequired) 即如果當前執行緒不是建立該form2的執行緒,則將方法通通過過invoke方法放到ui執行緒裡去執行。但就是這裡問題出現了。form1和form2都是在uithread裡建立的,所以它們儲存的執行緒的資訊應該是一樣的。所以form1.invokerquired和form2.invokerquired的值在任何執行緒裡都是一樣的,即在workerthread中invokerquire的值都應該是true(因為在不同的執行緒裡)。但是如果注釋掉form2.show()的話form2.invokerquired在workerthread中的值卻是false(在vs.net中除錯看到),怎麼會這樣呢?而且如果不經過判斷直接在workerthread裡呼叫form2物件的invoke的話…………居然會丟擲異常——「在建立視窗控制代碼之前,不能在控制項上呼叫 invoke 或 invokeasync」分析一下該異常的資訊,在win32裡每乙個窗體都有乙個窗體控制代碼,是該窗體在建立時系統分配的,但我們確實在ui執行緒裡建立了form2物件的。這裡有個誤區.net裡的form物件並不是和win32的窗體物件完全對應的。

本人竊以為,產生乙個form類的例項時,只是產生了乙個記憶體中的普通的物件,並不產生系統窗體(好像叫做user物件吧),只有它第一次呈現在螢幕上(或稱作建立)時,才產生系統裡表示窗體的user物件且分配控制代碼,對應的win32 api的createwindow()方法大概也在這個時候執行(先宣告:本人對win32 ap 並不熟悉,所以這裡如果有什麼不妥的話請大家指正)

只有.net裡的form物件呼叫某種方法使系統產生真正的窗體時,form才會有建立它的執行緒的資訊,且invokerquired才有效,即才能呼叫form的invoke方法。不過我還沒弄清楚哪幾個方法可以做到。據我所知show, creategraphics可以產生系統真正的系統窗體。

WinForm 多執行緒

winform多執行緒程式設計 1.new thread 新開乙個執行緒,執行乙個方法,沒有引數傳遞 private void dowork private void dosomething 新開乙個執行緒,執行乙個方法,並傳遞引數 private void dowork private void ...

winform 多執行緒錯誤集錦

1.thread.sleep 300 到底睡的是誰,哪個執行緒?1 public void setlabelinfo object num 2 7 8else920 21 累加顯示到label 中,第一次確實是btn發起的執行緒,name start clic 程,第二次顯示的主線程,所以threa...

WinForm多執行緒程式設計簡單Demo

ps 由於報告生成非常耗費資源,使用單執行緒程式設計模式,監控資訊根本無法資訊無法及時在richtext顯示.public partial class form1 form private void createrpt cancellationtoken ct invoke方法用於獲得建立lbl s...