發表文章

PB多線程自動排程設計(一)

圖片
多線程的設計主要是為了改進單線程自動排程的 問題 ,因此設計成多線程的執行方式來解決,但由於PowerBuilder本身沒有辦法設計MultiThread,因此改用多程式方(MultiProcess)式來模擬此方法。 既然是MultiProcess,那麼需要2支程式,一支是排程程式(Scahdule runner),與工作執行程式(Work Processor)。 排程程式:屬於獨立運作的程式,其內容相當單純,只負責排程表(Scahdule Table)的掃描(Scan)與執行呼叫(Call),由於本身不需要處理工作,因此沒有被工作延滯的可能性,單純的處理排程表的掃描,也可以減少多餘的程式碼維護。 工作執行程式:被動式程式,裡面會撰寫所有的工作程式碼,此程式可以被多次執行,由於在windows下一支程式可以被多次執行,而且不會互相干擾(這是指程式本身,不包含都在讀取相同資料庫的資料表產生的LOCK),所以利用windows的MultiProcess特性來達成模擬multiThread效果。 呼叫意示圖: 多重呼叫亦試圖: 由上圖看,好像需要寫出很多的WorkProcessor程式,但其實不然,在PB的application的OPEN事件中,可以取得CommandLine參數,該Processor程式只需要將所有工作寫在裡面,然後利用CommadnLine來判斷需要執行哪個工作程式碼即可完成。 呼叫方式: 假設排程程式是app.exe,工作執行程式是proc.exe,當排程掃描到此時該執行A工作時,只需要執行 Run('proc.exe A') 當proc.exe執行時,在其OPEN事件的參數CommandLine即可得到一個字串"A",在使用Choose Case來判定執行的程式碼片段。 當然這樣的程式設計也有它的優缺點 優點:排程、工作獨立分離,不互相干擾時序,運作流暢度高。 缺點:程式維護複雜、錯誤追蹤相當困難。 範例程式下載

PB單線式自動排程程式設計(二)

繼上一篇 PB單線式自動排程程式設計(一) 這篇來談談如何改進上一篇的STACK溢位問題吧。 其實這個方法並不難,但是要有足夠的觀念。 1.在原來的window上增加一個自訂事件ue_process 2.在window的共用變數(Instance variables)增加一個布林值 Boolean ib_busy = false 3.把原本在timer事件中的 程式碼全部移動到 ue_process事件中 4.在ue_process事件中的程式碼(不包含變數定義)開頭加入: ib_busy = true 在程式碼最後加入: ib_busy = false 5.在原本的timer事件中寫下下列程式碼: If ib_busy = false Then post event ue_process() End If 原理是利用旗標變數ib_busy來阻擋事件被觸發,當ue_process被執行時 ib_busy被設定為true,假設此時工作A發生問題時,timer事件的再觸發執行時可以透過ib_busy避免ue_process被觸發,如此ue_process就不會有一直被stack起來的問題。 那為何程式要移至ue_process事件?這是因為程式若移至ue_process事件後該工作被執行時stack指標是處在ue_process上,當clock觸發timer事件時,由於timer事件並無被stack住,所以可以順利的執行,因此不會被擋住,該事件可以被順利處理不會stack起來。 當然此法是可以避免timer觸發事件無法消化的問題導致stack溢位而crash發生,但是卻也沒辦法保證其它工作可以正常執行,因為只要有其中一個工作不正常,整個程式依然處在停擺狀態。 比較好的方式就是利用多執行緒撰寫程式,可惜powerbuilder並非用來設計低階處理的程式工具,因此無法像C/C#班可以設計多執行緒;當然山不轉路轉,不能設計多執行緒,但可以設計多執行程式,所以另一種方法便是利用多程式執行方式達到此效果。

PB單線式自動排程設計(一)

圖片
簡介: 這裡所謂單線式排程程式,意指排程掃描與工作處理程式都寫在同一支程式裡面,由於PowerBuild 6程式本身無法像C#般寫成多執行緒的能力,因此在同時處理許多作業時,都得依照程式碼執行的STACK順序執行,故名為"單線式" 準備與設計: 1.首先必須要有一分工作排程清單,例如每日工作 這樣的資料表結構你可以設計成DataWindow,當然你如果要增加欄位或是功能,都是可以的,不過基本上的結構是如此。 結構中"時"、"分"的欄位是用來比對是否進行工作的時間點,當時間行程到達該時間點時就得進行該工作的執行。 "執行時間"則是代表此工作"被執行完成"的時間點,這個用來判斷該工作是否已經被執行,而不會被重複執行的要件。 "啟用"則是決定該工作是否需要被執行,有的人會以另一種觀點"暫停"來設計。 "工作名稱"顧名思義只是用來顯示的名稱,讓人一目瞭然知道此工作的用途。 "代號"則是代表該工作在程式碼運作時的實際作業。 2.設計視窗: 設計一個window(w_app),並將上述排程DataWindow(dw_1)加入裡面。 另外設計一個MultiLineEdit,用以觀察執行結果。 3.程式碼撰寫: OPEN事件 由於排單位是以"分"為基礎比對單位,故時間的區隔就以"分"為準則,因此在w_app的Open事件中寫入Timer(60),表示以60秒觸發一次Timer事件。 TIMER事件 Long ll_count , ll_row ll_count = dw_1.RowCount() For ll_row = 1 to ll_count // 檢查該工作是否啟用,若不啟用則跳過 If dw_1.GetItemString(ll_row , 'active') '1' Then Continue // 檢查當天是否已經被執行過,若執行過者不再被執行 If date(dw_1.GetItemDatetime(ll_row , 'work_time')) >= today() then Continue /...