實戰.Net多執行緒(二)
在上一篇博文中,我們已經實現了簡單的非同步方法呼叫,但是還有兩個關鍵問題無法解決,1、我們無法知道非同步方法何時執行完畢;2、必須控制主執行緒上的button物件的enabled屬性,也就是說在非阻塞模式下不能對同一個button反覆的單擊。
我們注意到BeginInvoke方法所接受的另外兩個可選引數,第一個引數就是我們所感興趣的,它接受型別為AsyncCallBack型別的方法 - CallBack1!當非同步方法呼叫結束時會自動呼叫這個回撥方法。回撥方法實際上是在Win32開發時代很多Windows API函式經常用到的,某些API函式需要傳遞一個回撥函式的地址,當系統API執行完畢後自動執行自定義的回撥函式。
回撥方法傳遞過來一個IAsyncResult類行的引數ar,它表示非同步方法操作的狀態,IAsyncResult有一個非常有用的屬性IsCompleted,我們可以根據這個屬性的值來判斷非同步方法操作是否結束,繼而EndInvoke非同步方法。CallBack1方法也許應該這麼寫:
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MessageBox.Show("Asynchronous Method Invocation is OK.");
}
}
但是執行結果會發現,MessageBox訊息框並不是模式化的!顯示訊息框的同時,主窗體仍然可以獲得焦點,窗體的物件也同樣也可以操作。原來,這是在另一個獨立執行緒上執行的MessageBox,而並不是在主執行緒上。那麼我們該如何顯示一個模式化主窗體的訊息框呢?答案很簡單,必須實施執行緒間操作,這裡還是要用到委託。我們建立一個要在主執行緒上執行的方法,並且為這個方法定義一個委託。然後必須檢測控制元件的InvokeRequired屬性,在我們的例子中就是this,也就是主窗體Form1,這樣做的目的是判斷呼叫執行緒是否和主執行緒位於同一執行緒中,若不是同一執行緒,必須用Invoke將方法封裝起來以便在主執行緒中執行。程式碼如下:
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MethodInvoker updateUI = delegate
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
};
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
上一篇的博文中關於MethodInvoker的使用並不是這樣的啊?沒錯!這種形式在.Net 2.0下是新增的,MethodInvoker這句程式碼的意思是委託的型別以及實際方法的內容一次性定義完成。實際上下邊的程式碼與前述MethodInvoker寫法完全等同:
MethodInvoker updateUI;
private void ShowMsg()
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
}
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
updateUI = new MethodInvoker(ShowMsg);
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
挺有意思的吧?有興趣的朋友不妨試一試。
第一個關鍵問題我們已經順利解決,那麼關於button的狀態設定問題其實到這裡我們也已經解決了,因為我們已經可以做到在一個執行緒上訪問另一個執行緒的物件及方法了。完整的程式碼如下:
//呼叫同一個耗時的方法
private void a()
{
Thread.Sleep(10000);
}
//阻塞式呼叫
private void button1_Click(object sender, EventArgs e)
{
a();
MessageBox.Show("button1_Click will return!");
}
//非同步方法呼叫 方法1
private MethodInvoker simpleDelegate1;
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
simpleDelegate1 = new MethodInvoker(a);
simpleDelegate1.BeginInvoke(CallBack1, null);
MessageBox.Show("button2_Click will return!");
}
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MethodInvoker updateUI = delegate
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
button2.Enabled = true;
};
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
我們已經充分介紹了非同步方法呼叫的使用,在下一篇博文中我們將繼續探討.Net多執行緒的新寵兒BackgroundWorker!
我們注意到BeginInvoke方法所接受的另外兩個可選引數,第一個引數就是我們所感興趣的,它接受型別為AsyncCallBack型別的方法 - CallBack1!當非同步方法呼叫結束時會自動呼叫這個回撥方法。回撥方法實際上是在Win32開發時代很多Windows API函式經常用到的,某些API函式需要傳遞一個回撥函式的地址,當系統API執行完畢後自動執行自定義的回撥函式。
回撥方法傳遞過來一個IAsyncResult類行的引數ar,它表示非同步方法操作的狀態,IAsyncResult有一個非常有用的屬性IsCompleted,我們可以根據這個屬性的值來判斷非同步方法操作是否結束,繼而EndInvoke非同步方法。CallBack1方法也許應該這麼寫:
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MessageBox.Show("Asynchronous Method Invocation is OK.");
}
}
但是執行結果會發現,MessageBox訊息框並不是模式化的!顯示訊息框的同時,主窗體仍然可以獲得焦點,窗體的物件也同樣也可以操作。原來,這是在另一個獨立執行緒上執行的MessageBox,而並不是在主執行緒上。那麼我們該如何顯示一個模式化主窗體的訊息框呢?答案很簡單,必須實施執行緒間操作,這裡還是要用到委託。我們建立一個要在主執行緒上執行的方法,並且為這個方法定義一個委託。然後必須檢測控制元件的InvokeRequired屬性,在我們的例子中就是this,也就是主窗體Form1,這樣做的目的是判斷呼叫執行緒是否和主執行緒位於同一執行緒中,若不是同一執行緒,必須用Invoke將方法封裝起來以便在主執行緒中執行。程式碼如下:
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MethodInvoker updateUI = delegate
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
};
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
上一篇的博文中關於MethodInvoker的使用並不是這樣的啊?沒錯!這種形式在.Net 2.0下是新增的,MethodInvoker這句程式碼的意思是委託的型別以及實際方法的內容一次性定義完成。實際上下邊的程式碼與前述MethodInvoker寫法完全等同:
MethodInvoker updateUI;
private void ShowMsg()
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
}
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
updateUI = new MethodInvoker(ShowMsg);
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
挺有意思的吧?有興趣的朋友不妨試一試。
第一個關鍵問題我們已經順利解決,那麼關於button的狀態設定問題其實到這裡我們也已經解決了,因為我們已經可以做到在一個執行緒上訪問另一個執行緒的物件及方法了。完整的程式碼如下:
//呼叫同一個耗時的方法
private void a()
{
Thread.Sleep(10000);
}
//阻塞式呼叫
private void button1_Click(object sender, EventArgs e)
{
a();
MessageBox.Show("button1_Click will return!");
}
//非同步方法呼叫 方法1
private MethodInvoker simpleDelegate1;
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
simpleDelegate1 = new MethodInvoker(a);
simpleDelegate1.BeginInvoke(CallBack1, null);
MessageBox.Show("button2_Click will return!");
}
private void CallBack1(IAsyncResult ar)
{
if (ar.IsCompleted)
{
simpleDelegate1.EndInvoke(ar);
MethodInvoker updateUI = delegate
{
MessageBox.Show(this, "Asynchronous Method Invocation is OK.");
button2.Enabled = true;
};
if (this.InvokeRequired)
{
this.Invoke(updateUI);
}
else
{
updateUI();
}
}
}
我們已經充分介紹了非同步方法呼叫的使用,在下一篇博文中我們將繼續探討.Net多執行緒的新寵兒BackgroundWorker!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14325734/viewspace-422903/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 實戰.Net多執行緒(一)執行緒
- 實戰.Net多執行緒(三)執行緒
- 實戰.Net多執行緒(四)執行緒
- Java多執行緒之守護執行緒實戰Java執行緒
- 多執行緒實現多工二執行緒
- .NET 多執行緒執行緒
- 多執行緒(二)執行緒
- 多執行緒系列(二):多執行緒基礎執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 【Java多執行緒】輕鬆搞定Java多執行緒(二)Java執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- .NET下多執行緒初探執行緒
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- Java多執行緒程式設計模式實戰指南(二):Immutable Object模式Java執行緒程式設計設計模式Object
- 多執行緒學習(二)執行緒
- 多執行緒筆記 二執行緒筆記
- 多執行緒與高併發(二)執行緒安全執行緒
- 【C++併發實戰】(二)執行緒管理C++執行緒
- 【多執行緒高併發程式設計】二 實現多執行緒的幾種方式執行緒程式設計
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- 實驗--多執行緒執行緒
- iOS 多執行緒記錄(二)iOS執行緒
- 多執行緒二 基本技能執行緒
- Java多執行緒之二(Synchronized)Java執行緒synchronized
- Java多執行緒的使用(二)Java執行緒
- 多執行緒和多執行緒同步執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- Java多執行緒——執行緒Java執行緒
- 執行緒與多執行緒執行緒
- VC多執行緒 C++ 多執行緒執行緒C++
- 如何實現多執行緒執行緒
- 多執行緒原理實現執行緒
- c++11 新特性實戰 (一):多執行緒操作C++執行緒