三
異步執行Command命令
在 ADO
NET
以前
通過 Command 類(如 SqlCommand
OleDbCommand等)執行 SQL
命令的線程一定要停下來等待執行結果
ADO
NET
新增了異步程序訪問接口(asynchronous API)
讓線程發出命令後可以繼續執行接下去的程序代碼
而在 ADO
NET
當前的版本只有 SqlClient 支持異步程序訪問接口
以往編寫程序時
我們可以直接通過
NET Framework 所提供的多線程機制
或是以 Delegate 類包裝多線程的方式
在
NET Framework 所提供的異步架構下
設計調用執行 Command 對象實例
這些方法都是讓一條工作線程(Worker Thread)停止在後台中等待執行結果
一旦有結果後
工作線程再通過標准的機制告知結果
原本 ADO
NET 的 Command 對象執行 SQL 語法的方法有
ExecuteReader
ExecuteNonQuery
ExecuteXmlReader 以及 ExecuteScalar 等
搭配
NET
Framework 原來就提供的異步模型慣例
除了 ExecuteScalar 方法外
其余的方法都新增了以 Begin 和 End 關鍵字開始的一對方法
也就是說 ExecuteReader 方法是同步執行
若要以異步的方式執行相同的功能
則調用 BeginExecuteReader 和 EndExecuteReader 這一組方法
在
NET Framework 中
以 Begin 為字首的方法負責傳入同名方法所需的參數
而以 End
為字首的方法用來取回執行結果
例如某個方法的定義如下
public override int ExecuteNonQuery()
則以異步調用的起始方法定義如下
public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback
object stateObject)
Begin~ 系列的方法會多加存放回調方法(Delegation)的指針參數
也就是上述語法中的 callback 參數
並提供語法中的 stateObject參數
讓你設置想要帶到 End~ 對應方法的信息
而 Begin~ 系列方法最後返回的是代表異步執行狀態的 IAsyncResult 對象實例
而不是原本同步執行方法的返回結果
你可以藉此查詢異步執行的狀況
而獲得執行結果的方法定義如下
public int EndExecuteNonQuery(IAsyncResult asyncResult)
在調用與 Begin~ 對應的 End~ 方法時
需要帶入 Begin~ 方法所返回的 IAsyncResult
對象實例
異步執行完畢後
取回與原先同步執行方法相同的執行結果
由於我們在執行完 Command 對象訪問數據庫的方法後
都會返回對象
如 ExecuteReader 取回 DataReader實例
ExecuteNonQuery 取回受影響的記錄條數
ExecuteXmlReader 取回 XmlReader 實例
因此大概都需要通過End系列方法來獲得執行結果
否則這些結果就遺失在系統中
若要異步執行 Command 命令
另一個必需設置的是
數據庫連接字符串內要加上 async=true 屬性
若連接字符串沒有加上該屬性
而通過 Command對象實例調用異步執行的方法
則會產生異常(exception)
若 Command 通過連接執行時
重頭到尾都是以同步的方式執行
則依照默認 async=false 的方式設置比較節省資源
若某些命令需要同步執行
另一些需要異步執行
則可以考慮使用不同的連接
在介紹范例應用程序前
我們先稍微談一下
NET Framework 所提供的公共的異步運行應用程序設計模式
不只是 ADO
NET
在其他訪問耗時的程序編寫上
也都可以套用這個模式
NET Framework內置了讓應用程序異步運行的功能
讓你在編寫應用程序時
不會因為某些耗時等待的操作讓程序停止響應
操作界面停滯讓用戶感覺起來好像死機一樣
一般會以多線程的方式處理這種需求
但若你不熟悉線程的運行
或是想利用線程池(Thread Pool)的好處
都可以在較為耗時的操作上
采用
NET Framework 所提供的異步功能
一般來說文件 I/O
網絡訪問乃至於 Web Services 訪問
以及本節所討論的 DB 訪問等都較為耗時
NET Framework為這一類的類都提供了上述以 Begin~/End~開頭的非同步執行方法
而這些方法皆成對出現
當然
也有可能是自己編寫的方法其商業邏輯非常復雜
導致調用該方法後
需要等待一段時間來完成
這時還可以通過
NETFramework 所提供的委托(Delegate)類來創建異步運行
但是實際在我們的應用中
但我們不需要獲知DB服務器的返回信息時
我們推薦使用委托
尤其是在Web開發中
因為在頁面線程啟動異步數據庫訪問時
當頁面業務執行完畢後仍然無法放開訪問數據庫的異步線程
這是我們不希望看到的
但是使用委托卻可以避免這個麻煩(webservice異步應用中一樣如此)
From:http://tw.wingwit.com/Article/program/net/201311/13138.html