如果你有一個應(yīng)用程序必須不停止的工作或表太大以致于應(yīng)用程序不能在為它建立索引是停止下來,你將面臨這樣的問題:如果工作站或服務(wù)器崩潰,索引被破壞并要求重建時,應(yīng)該怎么辦?
有一個好的理由讓你的表單和報表是基于視圖的而不是基于表的。你可以讓一個視圖離線,并在用戶繼續(xù)查詢或數(shù)據(jù)輸入時重建索引。一但索引完成,從離線視圖把數(shù)據(jù)更新到源表。僅需要短暫的中斷來讓視圖離線后更新源表并重新讓視圖聯(lián)線。事實上,如果你需要進(jìn)行常規(guī)的重建索引,你可以考慮使用離線視圖,并周期性的短時聯(lián)線時間進(jìn)行重建索引工作。
一個小的復(fù)雜的地方是,如何關(guān)閉各工作站上的視圖足夠長的時間來使視圖離線(以及連線) 而不需要打電話告訴各個用戶告訴他們關(guān)閉數(shù)據(jù)輸入表單一會?我使用的方法是一種“旗語”方案:各數(shù)據(jù)輸入表單監(jiān)視一個需要維護(hù)的信號。當(dāng)接收到該信號時,表單關(guān)閉,然后應(yīng)用程序等待第二個視圖狀態(tài)已改變的信號(離線或聯(lián)線),然后數(shù)據(jù)輸入可以繼續(xù)下去。在收到第二個信息前,用戶不能訪問數(shù)據(jù)輸入表單或任何使用視圖的報表。
監(jiān)視信號的基礎(chǔ)是計時器對象。在該方案中居然使用了三個有關(guān)的計時器:
重索引表單中的計時器用于執(zhí)行重建索引時的等待,直到所有用戶關(guān)閉了視圖。然后讓視圖離線或聯(lián)線(這要看是否重建索引是開始了或已經(jīng)完成) 并傳送信號到應(yīng)用程序級的計時器。
在數(shù)據(jù)輸入表單中的計時器等待一個信號時,視圖必須改變狀態(tài)。當(dāng)接收到該信號時,表單關(guān)閉且一個應(yīng)用程序級的計時器開始工作。
應(yīng)用程序級的計時器,它僅在等待視圖的修改狀態(tài)時被啟用,監(jiān)視來自重索引表單中的視圖狀態(tài)改變信號,這樣數(shù)據(jù)輸入和查詢可以繼續(xù)。
當(dāng)你解壓本文所附的源代碼(在第二節(jié))時,會在REINDEX 目錄中生成一些文件。以下是這些文件中的一部分:
SYSINFO.DBF 是一個包含一個邏輯字段CHNGSTATE 的表(ChangeState的縮寫)。該字段在通常情況下的值為.F.,當(dāng)它的值被設(shè)置為.T.時,它反映了視圖中所有的該狀態(tài)的塊必須修改。該表在應(yīng)用程序運行過程中始終是打開的。
應(yīng)用程序菜單中的所有功能都需要一個Skip For SYSINFO.CHNGSTATE 。因此當(dāng)視圖的該狀態(tài)被修改時,用戶不能訪問該功能。
任何使用視圖的數(shù)據(jù)輸入表單都有一個計時器對象,在其Timer() 事件中的代碼關(guān)閉表單并啟用一個應(yīng)用程序級的計時器,如果 SYSINFO.CHNGSTATE 變?yōu)?T。以下是CUSTOMER 表單中的計時器對象中的代碼 (在該代碼中,oTimer 是應(yīng)用程序級的計時器):
if SYSINFO.CHNGSTATE
messagebox(’Closing form to perform maintenance?!?+ ;
’The form will automatically reopen in just a ’ + ;
’moment.’,48)
oTimer.Enabled = .T.
Thisform.Release()
endif SYSINFO.CHNGSTATE
在應(yīng)用程序啟動時,一個計時器對象被實例化但是被廢止的(disabled)。該計時器 僅在表單因視圖處于修改狀態(tài)而被強(qiáng)制關(guān)閉時啟用,在它的Timer() 事件event 代碼中搜索SYSINFO.CHNGSTATE 是否為.F.因此它可以重新打開任何因視圖處于修改狀態(tài)而被強(qiáng)制關(guān)閉的表單。以下是其代碼在(在類庫MYAPP.VCX 中的MyApp計時器類)中:
if not SYSINFO.CHNGSTATE
This.Enabled = .F.
do form CUSTOMER
endif not SYSINFO.CHNGSTATE
當(dāng)然,這些代碼是硬編碼來打開CUSTOMER 表單,因為它是本例中指定的表單。在一個真正的應(yīng)用程序中,你可以用一個管理對象在關(guān)閉表單將它注冊到應(yīng)用程序的INI文件中,管理器對象負(fù)責(zé)再次啟動各個表單的備份。
一個用于重建索引的表單,當(dāng)用戶開始重索引時或已完成時設(shè)置SYSINFO.CHNGSTATE 為 .T. 并啟動計時器。正象我們已看到的那樣,設(shè)置SYSINFO.CHNGSTATE 通知所有工作站上的所有打開的表單,它需要啟動應(yīng)用程序范圍的計時器然后關(guān)閉它自己。重索引表單計時器使用試著以獨占方式打開視圖的方法來定期檢查所有用戶已經(jīng)關(guān)閉視圖。一但可以以獨占方式打開視圖,視圖離線或聯(lián)線 (首先更新源表),并且 SYSINFO.CHNGSTATE 設(shè)置回.F.(通知應(yīng)用程序級計時器數(shù)據(jù)輸入可以繼續(xù))。以下是REINDEX 表單的計時器對象的Timer() 事件的代碼:
with Thisform
* Disable 計時器(因此當(dāng)我們執(zhí)行這此代碼時它不會激活)
* 并看我們是否可以以獨占方式打開該視圖。
This.Enabled = .F.
.CloseTables()
select 0
use LV_CUSTOMER exclusive
do case
* 我們可以打開該視圖,因此再關(guān)閉它,我們自己disable它
* 并轉(zhuǎn)換視圖的狀態(tài).
case used(’LV_CUSTOMER’)
.CloseTables()
有一個好的理由讓你的表單和報表是基于視圖的而不是基于表的。你可以讓一個視圖離線,并在用戶繼續(xù)查詢或數(shù)據(jù)輸入時重建索引。一但索引完成,從離線視圖把數(shù)據(jù)更新到源表。僅需要短暫的中斷來讓視圖離線后更新源表并重新讓視圖聯(lián)線。事實上,如果你需要進(jìn)行常規(guī)的重建索引,你可以考慮使用離線視圖,并周期性的短時聯(lián)線時間進(jìn)行重建索引工作。
一個小的復(fù)雜的地方是,如何關(guān)閉各工作站上的視圖足夠長的時間來使視圖離線(以及連線) 而不需要打電話告訴各個用戶告訴他們關(guān)閉數(shù)據(jù)輸入表單一會?我使用的方法是一種“旗語”方案:各數(shù)據(jù)輸入表單監(jiān)視一個需要維護(hù)的信號。當(dāng)接收到該信號時,表單關(guān)閉,然后應(yīng)用程序等待第二個視圖狀態(tài)已改變的信號(離線或聯(lián)線),然后數(shù)據(jù)輸入可以繼續(xù)下去。在收到第二個信息前,用戶不能訪問數(shù)據(jù)輸入表單或任何使用視圖的報表。
監(jiān)視信號的基礎(chǔ)是計時器對象。在該方案中居然使用了三個有關(guān)的計時器:
重索引表單中的計時器用于執(zhí)行重建索引時的等待,直到所有用戶關(guān)閉了視圖。然后讓視圖離線或聯(lián)線(這要看是否重建索引是開始了或已經(jīng)完成) 并傳送信號到應(yīng)用程序級的計時器。
在數(shù)據(jù)輸入表單中的計時器等待一個信號時,視圖必須改變狀態(tài)。當(dāng)接收到該信號時,表單關(guān)閉且一個應(yīng)用程序級的計時器開始工作。
應(yīng)用程序級的計時器,它僅在等待視圖的修改狀態(tài)時被啟用,監(jiān)視來自重索引表單中的視圖狀態(tài)改變信號,這樣數(shù)據(jù)輸入和查詢可以繼續(xù)。
當(dāng)你解壓本文所附的源代碼(在第二節(jié))時,會在REINDEX 目錄中生成一些文件。以下是這些文件中的一部分:
SYSINFO.DBF 是一個包含一個邏輯字段CHNGSTATE 的表(ChangeState的縮寫)。該字段在通常情況下的值為.F.,當(dāng)它的值被設(shè)置為.T.時,它反映了視圖中所有的該狀態(tài)的塊必須修改。該表在應(yīng)用程序運行過程中始終是打開的。
應(yīng)用程序菜單中的所有功能都需要一個Skip For SYSINFO.CHNGSTATE 。因此當(dāng)視圖的該狀態(tài)被修改時,用戶不能訪問該功能。
任何使用視圖的數(shù)據(jù)輸入表單都有一個計時器對象,在其Timer() 事件中的代碼關(guān)閉表單并啟用一個應(yīng)用程序級的計時器,如果 SYSINFO.CHNGSTATE 變?yōu)?T。以下是CUSTOMER 表單中的計時器對象中的代碼 (在該代碼中,oTimer 是應(yīng)用程序級的計時器):
if SYSINFO.CHNGSTATE
messagebox(’Closing form to perform maintenance?!?+ ;
’The form will automatically reopen in just a ’ + ;
’moment.’,48)
oTimer.Enabled = .T.
Thisform.Release()
endif SYSINFO.CHNGSTATE
在應(yīng)用程序啟動時,一個計時器對象被實例化但是被廢止的(disabled)。該計時器 僅在表單因視圖處于修改狀態(tài)而被強(qiáng)制關(guān)閉時啟用,在它的Timer() 事件event 代碼中搜索SYSINFO.CHNGSTATE 是否為.F.因此它可以重新打開任何因視圖處于修改狀態(tài)而被強(qiáng)制關(guān)閉的表單。以下是其代碼在(在類庫MYAPP.VCX 中的MyApp計時器類)中:
if not SYSINFO.CHNGSTATE
This.Enabled = .F.
do form CUSTOMER
endif not SYSINFO.CHNGSTATE
當(dāng)然,這些代碼是硬編碼來打開CUSTOMER 表單,因為它是本例中指定的表單。在一個真正的應(yīng)用程序中,你可以用一個管理對象在關(guān)閉表單將它注冊到應(yīng)用程序的INI文件中,管理器對象負(fù)責(zé)再次啟動各個表單的備份。
一個用于重建索引的表單,當(dāng)用戶開始重索引時或已完成時設(shè)置SYSINFO.CHNGSTATE 為 .T. 并啟動計時器。正象我們已看到的那樣,設(shè)置SYSINFO.CHNGSTATE 通知所有工作站上的所有打開的表單,它需要啟動應(yīng)用程序范圍的計時器然后關(guān)閉它自己。重索引表單計時器使用試著以獨占方式打開視圖的方法來定期檢查所有用戶已經(jīng)關(guān)閉視圖。一但可以以獨占方式打開視圖,視圖離線或聯(lián)線 (首先更新源表),并且 SYSINFO.CHNGSTATE 設(shè)置回.F.(通知應(yīng)用程序級計時器數(shù)據(jù)輸入可以繼續(xù))。以下是REINDEX 表單的計時器對象的Timer() 事件的代碼:
with Thisform
* Disable 計時器(因此當(dāng)我們執(zhí)行這此代碼時它不會激活)
* 并看我們是否可以以獨占方式打開該視圖。
This.Enabled = .F.
.CloseTables()
select 0
use LV_CUSTOMER exclusive
do case
* 我們可以打開該視圖,因此再關(guān)閉它,我們自己disable它
* 并轉(zhuǎn)換視圖的狀態(tài).
case used(’LV_CUSTOMER’)
.CloseTables()