[C#] 非同步委派測試(關閉表單時會錯誤)
今天在練習非同步委派,這邊隨手記錄一下。這邊使用表單來實作,
雖然表單不會 Lock 住,但在測試時,發現若是直接關閉表單會出現錯誤,
若是在關閉時結束委派作業,不過程式會停在那邊,還找不出原因。
之前在實作 BackgroundWorker ,也遇過相同情形;我在
FormClosing 事件下,取消了背景作業。(程式碼如下)
//關閉表單發生時
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
//取消背景作業
this.CancelBackgroundWork();
}
在實作非同步委派時,又該如何結束委派作業呢?
查看 msdn 的說明,使用 EndBegin() 函式,卻使程式當住。
程式碼範例
//引用命名空間
using System.Runtime.Remoting.Messaging;
namespace CallBackDemo {
public partial class Form1 : Form {
//宣告委派型別
private delegate string _del(string value,Control ctl);
private delegate void _del2(string value, Control ctl);
//宣告委派變數
private _del Mydel = null;
private IAsyncResult MyAsyncReseult = null;
private AsyncCallback MyCallback = null;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
}
private void btnStart_Click(object sender, EventArgs e) {
btnStart.Enabled = false;
//建立委派物件
Mydel = new _del(DoUpdate);
//建立 Callback 物件
MyCallback = new AsyncCallback(CallBackMethod);
//執行非同步委派,主執行緒會繼續往下走
MyAsyncReseult = Mydel.BeginInvoke("1", textBox1, MyCallback, null);
}
//更新資料
private string DoUpdate(string value, Control ctl) {
int iNumber = int.Parse(value);
while (true) {
iNumber++;
UpdateUI(iNumber.ToString(), textBox1);
if (iNumber == 100000){
break;
}
}
return iNumber.ToString();
}
private void UpdateUI(string value, Control ctl) {
//判斷是否 [非] UI 執行緒
if (this.InvokeRequired) {
_del2 myUpdate = new _del2(UpdateUI);
//強制使用 UI 執行緒來執行委派
if (!this.IsDisposed) {
this.Invoke(myUpdate, value, ctl);
} else { return; }
} else {
ctl.Text = value;
}
}
//當委派執行完成後,會回呼這個函式
private void CallBackMethod(IAsyncResult ar) {
//這邊執行其他作業
//......
//......
//結束 Callback
//取得叫用時委派物件
_del callback = (_del)((AsyncResult)ar).AsyncDelegate;
//完成非同步呼叫
string sResult = callback.EndInvoke(ar);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
Mydel.EndInvoke(MyAsyncReseult);
MyAsyncReseult.AsyncWaitHandle.Close();
}
}
}
懷疑是否與傳入的 callback 委派有關?
不過還是無法解決 = = 。
輸出
程式碼屍體 CallBackDemo.rar
<<後記>>
感謝 Bill Chung 大的提點,提供連結 http://www.dotblogs.com.tw/billchung/archive/2009/04/04/7851.aspx
還原問題:
當我點選關閉表單時,應該是要順利的關閉應用程式,不過因為使用非同步委派,產生了另外一條執行緒去執行更新表單的作業,
這時,當我按下關閉,當執行緒要去更新表單時,就會出現錯誤,如圖
我嘗試在程式中加入
this.IsDisposed
依然無效。最後參考 Bill Chung 大的程式碼範例,程式加入 try catch 濾掉例外,程式即可順利關閉
try {
if (!this.IsDisposed) {
this.Invoke(myUpdate, value, ctl);
} else { return; }
}
catch (ObjectDisposedException objex) {
//不做任何處理
}
catch (ThreadAbortException aboex) {
//不做任何處理
}
程式碼下載 CallBackDemo.rar
三小俠 小弟獻醜,歡迎指教