天天看點

ADO異步查詢顯示進度條

    一般, A D O都是以同步的方式來處理資料。這就是說,當A D O開始處理資料後,應用程式必須等到A D O處理完畢之後才可以繼續執行。但是除了同步執行方式之外, A D O也提供了異步執行的方式,允許當A D O處理時,應用程式仍然能夠先繼續執行。而當A D O處理資料完畢之後, A D O會以事件的方式通知應用程式,此時應用程式可以再根據A D O執行的結果來采取相應的動作。

    使用異步執行方式有許多用途,例如,如果應用程式需要處理花費大量時間的動作,那麼A D O可以選擇以異步執行方式讓A D O在背景執行,而讓應用程式繼續處理圖形使用者接口或使用者輸入的資料。

    在A D O中使用異步執行方式非常簡單,隻需要對A D O資料集的E x e c u t e O p t i o n s屬性值進行适當的設定即可。現在就讓我們以一實際的範例應用程式來說明如何讓A D O以異步的方式來處理資料。

1) 在D e l p h i內建開發環境中關閉所有的項目。

2) 建立一個新的應用程式項目,在主窗體中放入TA D O C o n n e c t i o n對象連接配接到資料庫。

3) 在主窗體中放入TA D O D a t a S e t元件。設定它的C o n n e c t i o n屬性值為步驟2) 的TA D O C o n n e c t i o n,并且在它的C o m m a n d Te x t屬性值中使用Select * from ADOTe s t D a t a s以取得所有的資料。再設定它的A c t i v e屬性值為Tr u e以打開範例資料表。

4) 放入TDataSource元件,設定它的DataSet屬性值為步驟3) 加入的TADODataSet元件。

5) 放入T D B N a v i g a t o r和T D B G r i d元件,設定它們的D a t a S o u r c e元件為步驟4加入的T D a t a S o u r c e元件。

6) 在主窗體中放入兩個T B u t t o n元件以及一個T P r o g r e s s B a r元件,并且設定它的相關屬性值。

7) 最後在主窗體中放入一個TA D O C o m m a n d元件。設定它的C o n n e c t i o n屬性值為步驟2) 的TA D O C o n n e c t i o n,并且在它的C o m m a n d Te x t屬性值中使用S e l e c t count(*) from ADOTe s t D a t a s以便從A D O Te s t D a t a s資料表中取得所有資料的筆數。

8) 在主窗體的O n A c t i v a t e事件處理程式中撰寫如下的程式代碼:

p r o c e d u r e TForm1.FormActivate(Sender: TObject);

v a r

    sRecNo : String;

b e g i n

    ProgressBar1.Max := ADOCommand1.Execute.Fields.Item[0].Value;

    sRecNo := IntToStr(ProgressBar1.Max);

    Self.Caption := '共有' + sRecNo + ' 筆資料' ;

e n d ;

O n A c t i v a t e事件處理程式首先執行TA D O C m m a n d的S Q L指令,并且從它回傳的暫時R e c o r d s e t對象中取出A D O Te s t D a t a s資料表中所有資料的筆數,然後再指定給T P r o g r e s s B a r的M a x值,最後指定給窗體的C a p t i o n屬性值。

9) 輕按兩下窗體中的e o A s y n c F e t c h N o n B l o c k i n g按鈕,并且在它的O n C l i c k事件處

理程式中撰寫如下的程式代碼:

p r o c e d u r e TForm1.Button2Click(Sender: TObject);

t r y

    ADODataSet1.Active := False;

    ADODataSet1.ExecuteOptions := [eoAsyncFetchNonBlocking];

f i n a l l y

    lStart := GetTickCount;

    ADODataSet1.Active := True;

在上面的程式代碼中先關閉步驟3) 的TA D O D a t a S e t,再設定它的E x e c u t e O p t i o n s屬性值為使用異步方式來存取資料。最後再打開步驟3) 的TA D O D a t a S e t元件,從A D O Te s t D a t a s資料表中取得資料。

10) 輕按兩下窗體中的e o A s y n c F e t c h按鈕,并且在它的O n C l i c k事件處理程式中撰

寫如下的程式代碼:

p r o c e d u r e TForm1.Button1Click(Sender: TObject);

    ADODataSet1.ExecuteOptions := [eoAsyncFetch];

在上面的程式代碼中先關閉步驟3) 的TA D O D a t a S e t,再設定它的E x e c u t e O p t i o n s屬性值為使用同步方式來存取資料,再打開步驟3) 的TA D O D a t a S e t元件,從A D O Te s t D a t a s資料表中取得資料。

在異步方式中, A D O會以O n F e t c h P r o g r e s s事件來通知應用程式A D O還在處理資料之中,并且以O n F e t c h C o m p l e t e事件來通知應用程式A D O已經處理資料完畢了。

程式員可以在這兩個事件處理程式中撰寫程式代碼來處理這兩種情形。下面是範例應用程式在這兩個事件處理程式中實作的程式代碼。

11) 在步驟3) 的TA D O D a t a S e t元件的O n F e t c h P r o g r e s s事件處理程式中撰寫如下的程式代碼:

p r o c e d u r e TForm1.ADODataSet1FetchProgress(DataSet: TCustomADODataSet;

Progress, MaxProgress: Integerv; a r EventStatus: TEventStatus);

 //注意,每次循環的進度步距不是1,在這有可能是15,第一次提取的記錄數量也很大,是以對于小資料量,沒有意義

    ProgressBar1.Position := Progress;

上面的程式代碼隻是在A D O持續處理資料時不斷更新主窗體中T P r o g r e s s B a s e

的顯示狀态。

12) 在步驟3) 的TA D O D a t a S e t元件的O n F e t c h C o m p l e t e事件處理程式中撰寫如下的程式代碼:

p r o c e d u r e TForm1.ADODataSet1FetchComplete(DataSet: TCustomADODataSet;

c o n s t Error: Error; v a r EventStatus: TEventStatus);

    lEnd := GetTickCount;

    S h o w M e s s a g e ( '總共花了' + FloatToStr((lEnd - lStart) / 1000.0) 秒+ ' ') ;

上面的程式代碼是當A D O處理完資料之後便顯示一個對話框,顯示A D O處理資料所花費的時間。

現在請編譯并且執行這個範例應用程式。圖3 - 1 3是以異步的方式來存取A D O Te s t D a t a s這個範例資料表中資料的畫面。從圖中可以看到,當A D O存取資料時應用程式仍然可以不斷地更新主窗體中的T p r o g r e s s B a r。如果使用同步的方式執

行,T P r o g r e s s B a r便無法這樣更新狀态。此時我們也可以移動主窗體的位置等,可見應用程式不會因為A D O在存取大量的資料而造成應用程式無法繼續工作。

當A D O以異步的方式執行時,O n F e t c h P r o g r e s s和O n F e t c h C o m p l e t e事件可以幫助程式員取得非常有用的狀态資訊。

如果你也執行這個範例應用程式,那麼可以比較一下當A D O在同步執行模式和異步執行模式中處理資料時哪一種模式比較有效率。可能你會驚訝地發現異步執行模式可以提供更好的執行效率

(邦畿千裡,摘自李維《Delphi 5.x ADO/MTS/COM+進階程式設計篇》,并進行整理)