本周做了一個線程中打開多個窗體的東西,父窗體打開子窗體,父窗體獲取子窗體的控件值,此處我在打開窗體時,分別在不同的線程中打開的,不做多考慮,上手就做,到后來程序崩掉了,原因是什么了,找不到對應的控件,這是為什么了,因為創建子窗體的過程和創建父窗體的過程並不在同一線程中,程序無法獲知你要找的控件,那么對於這種情況,就得用到vs自帶的Control.InvokeRequired方法,此方法返回的結果為bool類型,主要是“ 獲取一個值,該值指示調用方在對控件進行方法調用時是否必須調用 Invoke 方法,因為調用方位於創建控件所在的線程以外的線程中。”
關於Invoke()方法,傳遞參數為一個方法委托,它采用的參數的數量和類型與 args 參數中所包含的相同。摘要: 在擁有控件的基礎窗口句柄的線程上,用指定的參數列表執行指定委托。
詳例說明
//第一步:打開窗體 SendEmailProgress progress = new SendEmailProgress(); progress.Closing += (s, ev) => { if (progress.IsEnabledCloseForm) { progress.IsAlreadyClosed = true; TaxCardFactory.ReleaseCard(); } else { ev.Cancel = true; CommonClass.Message("323", "", null); } }; Control.CheckForIllegalCrossThreadCalls = false; //在這個類中我們不檢查跨線程的調用是否合法 thread = new Thread(new ParameterizedThreadStart(ShowCommonProgressFormDialog)); thread.Start(); SendEmailProgress.TaxCardInfo info = progress.GetCardInfo("AutoExtract", taxCardModel);
SendEmailProgress.cs文件 錯誤的代碼: public TaxCardInfo GetCardInfo(string type, ITaxCard card) { using (EditTaxCardPwd editTaxCardForm=new EditTaxCardPwd(type,card)) { if (editTaxCardForm.ShowDialog(this) != DialogResult.OK) { return null; } return new TaxCardInfo() { CardPwd = editTaxCardForm.goldenPlatePwd }; } } 正確的代碼: public TaxCardInfo GetCardInfo(string type, ITaxCard card) { if (InvokeRequired) { return this.Invoke(new Func<string, ITaxCard,TaxCardInfo>(GetCardInfo),type,card) as TaxCardInfo;
//這種寫法等同於定義一個委托方法,比如:
//private delegate void GetCardInfoHandler(string type, ITaxCard card);
//GetCardInfoHandler InfoHandler=GetCardInfo; return this.Invoke(GetCardInfoHandler,new object[]{type,card}); } using (EditTaxCardPwd editTaxCardForm=new EditTaxCardPwd(type,card)) { if (editTaxCardForm.ShowDialog(this) != DialogResult.OK) { return null; } return new TaxCardInfo() { CardPwd = editTaxCardForm.goldenPlatePwd }; } }
同時,需要注意的是如果線程中打開某個窗體,並且要為打開的窗體附加樣式,一定要確保加載樣式的邏輯和打開窗體的邏輯在同一個線程里!!!!!
此文僅做個人積累。。。。。。。