本文轉載:http://blog.csdn.net/playing9c/article/details/7471918
http://blog.csdn.net/beelinkerlidejun/article/details/4772491
http://www.cnblogs.com/fish124423/archive/2012/10/16/2726543.html
C#窗體的多線程一直是個難題,總是要出現奇奇怪怪的錯誤。今天開發alexSEO軟件時,出現了在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。主要出現問題代碼如下:
protected override void OnLoad(EventArgs e) { base.OnLoad(e); txtRFID_Click(null, null); }
private void txtRFID_Click(object sender, EventArgs e) { Thread thread = new Thread(() => { if (this.IsHandleCreated) this.BeginInvoke(new MethodInvoker(() => { this.txtRFID.Enabled = false; })); int iRet = -1; string strTid = ""; iRet = WriteCardHelper.Instance.ReadTID(ref strTid); //讀取耗時的代碼;
//注意:耗時的代碼不能放在 this.BeginInvoke(new MethodInvoker(() => 耗時代碼 })); //中執行;否則沒有產生異步的效果。
//BeginInvoke中只能放置操作控件的代碼。BeginInvoke將子線程線程通過委托拋向UI主線程 。 if (this.IsHandleCreated) this.BeginInvoke(new MethodInvoker(() => { this.errorProvider.SetError(this.txtRFID, ""); if (0 == iRet) { WriteCardHelper.Instance.SetAlarm(); this.txtRFID.Text = strTid; this.txtRFID.BackColor = Color.White; this.errorProvider.SetError(this.txtRFID, ""); } else { this.txtRFID.Text = ""; this.txtRFID.BackColor = Color.Pink; } this.txtGasBottleNo.Focus(); this.txtRFID.Enabled = true; })); }); thread.IsBackground = true; thread.Start(); }
客戶端:(實現異步打開窗體,該窗體加載的時候會讀取設備的數據,但會很耗時,為了防止窗體加載時候由於耗時的代碼,導致不能及時的顯示出來)
frmGasBottlesInstall frmInstall = new frmGasBottlesInstall(gasBottlesID); frmInstall.ShowDialog(); //異步打開窗口。
當調試運行中突然關閉軟件時,labb.Invoke(labchange);語句就出先了“在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。”錯誤。想了一通出現這種情況應該有兩種可能。第一種應該是界面還來不及響應Invoke,第二種是界面線程已經結束,所以響應不了。最后解決辦法是在labb.Invoke(labchange);前加一個if(labb.IsHandleCreated)判斷就可以了。
