本周做了一个线程中打开多个窗体的东西,父窗体打开子窗体,父窗体获取子窗体的控件值,此处我在打开窗体时,分别在不同的线程中打开的,不做多考虑,上手就做,到后来程序崩掉了,原因是什么了,找不到对应的控件,这是为什么了,因为创建子窗体的过程和创建父窗体的过程并不在同一线程中,程序无法获知你要找的控件,那么对于这种情况,就得用到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 }; } }
同时,需要注意的是如果线程中打开某个窗体,并且要为打开的窗体附加样式,一定要确保加载样式的逻辑和打开窗体的逻辑在同一个线程里!!!!!
此文仅做个人积累。。。。。。。