| ??????? 某些場(chǎng)合下,在對(duì)數(shù)據(jù)庫進(jìn)行訪問時(shí),為了避免同步訪問數(shù)據(jù)時(shí)所帶來的延遲,我們需要改進(jìn)設(shè)計(jì),以提高程序執(zhí)行效率。一方面,這可以給用戶以良好的使用體驗(yàn);另一方面,也降低了程序崩潰的可能性。為實(shí)現(xiàn)這一目的,我們采用異步方式來訪問數(shù)據(jù)庫。 ??????? 什么是異步呢?簡(jiǎn)單來說,就是并行執(zhí)行。它與同步是相對(duì)立的,我們平時(shí)所有用到的方式大都屬于同步執(zhí)行。比如,在一段程序中,標(biāo)號(hào)為 B 的語句在標(biāo)號(hào)為 A 的語句后面,那行,如果 A 語句沒有執(zhí)行完,那么 B 語句就得不到執(zhí)行。而異步則不同,我們可以把異步執(zhí)行理解為輕型線程。當(dāng)程序在 A 處開始異步執(zhí)行的時(shí)候,主程序繼續(xù)執(zhí)行,而異步語句中指定的操作則在后臺(tái)線程上與主線程同時(shí)執(zhí)行。因此,它提高了程序執(zhí)行的效率,也減少了阻塞的可能。 ??????? 實(shí)現(xiàn)異步的方法有多種,這里我們采用異步回調(diào)方式,使用異步回調(diào)時(shí),我們需要實(shí)例化 AsyncCallback 委托,這是系統(tǒng)定義的委托。在 .NET 中,提供了一系列用于異步操作的方法。每種異步操作通常包含了兩個(gè)方法,即 BeginXXX() 和 EndXXX()。比如,我們下面即將要用到的 BeginExecuteReader() 和 EndExecuteReader()。 ??????? 請(qǐng)看代碼(本文采用 C# 語言): using System; using System.ComponentModel; using System.Data; using System.Text; using System.Data.SqlClient; using System.Drawing; using System.Windows.Forms; namespace 異步訪問數(shù)據(jù)庫 { //定義一個(gè)委托,這個(gè)委托在下面顯示數(shù)據(jù)時(shí)會(huì)用到,它接受一個(gè) DataTable 類型的參數(shù) ??? public delegate void ShowData(DataTable dt); ??? //窗體類 ??? public partial class UsingCallBack : Form ??? { ??????? DataSet ds = new DataSet(); ??????? ShowData sd; //定義委托變量 ??????? public UsingCallBack() ??????? { ??????????? InitializeComponent(); ??????????? this.StartPosition = FormStartPosition.CenterScreen; ??????? } ??????? private void UsingCallBack_Load(object sender, EventArgs e) ??????? { //為委托指定方法 ??????????? sd = new ShowData(this.ShowDataFunction); ??????? } ??????? private void button1_Click(object sender, EventArgs e) ??????? { ??????????? //定義異步回調(diào)委托 ??????????? AsyncCallback ac=new AsyncCallback(CallbackProcedure); ??????????? this.Text = "正在異步讀取數(shù)據(jù)庫,您可以執(zhí)行其它操作..."; ??????????? //定義數(shù)據(jù)庫變量 ??????????? SqlConnectionStringBuilder cSB = new SqlConnectionStringBuilder(); ??????????? cSB.ConnectionString = "Server=.;Initial Catalog=Northwind;Integrated Security=True"; ???? //這一步是最關(guān)鍵的,用 AsynchronousProcessing 的屬性來指定是否可以執(zhí)行異步操作 ??????????? cSB.AsynchronousProcessing = true; ??????????? SqlConnection sqlCon = new SqlConnection(cSB.ConnectionString); ??????????? string SQL = "Select * From Orders"; ??????????? SqlCommand sqlCmd = new SqlCommand(SQL, sqlCon); ??????????? sqlCon.Open(); //開始異步讀取 ??????????? sqlCmd.BeginExecuteReader(ac, sqlCmd); ????????????? ??????? } //異步回調(diào)過程,在異步操作完成時(shí)調(diào)用,故稱回調(diào) ??????? public void CallbackProcedure(IAsyncResult ar) { ??????????? SqlDataReader sDR; ??????????? SqlCommand sqlCmd = (SqlCommand)ar.AsyncState; ??????????? sDR = sqlCmd.EndExecuteReader(ar); ??????????? ds.Load(sDR, LoadOption.OverwriteChanges, "Result"); //執(zhí)行委托:這個(gè)委托我們?cè)谧钌厦嬉呀?jīng)定義過,它負(fù)責(zé)將執(zhí)行結(jié)果顯示 ??????????? Invoke(sd, ds.Tables["Result"]);??????????? ??????? } ??????? public void ShowDataFunction(DataTable dt) { ???? //將 DataGridView 的 DataSouce 屬性值設(shè)為傳過來的 DataTable ??????????? this.DGV.DataSource =dt; ??????? } ??? } } ??????? 通過上述程序,我們可以看到,在異步訪問數(shù)據(jù)庫時(shí),我們需要使用對(duì)象 SqlConnectionStringBuilder ,只有當(dāng)該對(duì)象的 AsynchronousProcessing 屬性為 True 時(shí),我們才能執(zhí)行異步操作。 對(duì)于上述程序,如果您有不了解的地方或者改進(jìn)意見,可以留言;如果需要全部源代碼,也可以留言。希望我們能共同交流。 |