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