多線程是指一個程序內部同時執行的多個流程,與單線程相比,它至少有兩個方面的優點:第一,它可以更好地利用系統資源,比如CPU,若一個線程因I/O操作受阻,另一個線程仍可利用CPU來執行;第二,它更好地滿足了客戶的需求,因爲挑剔的客戶希望你開發的程序在顯示動畫的同時還能播放音樂、顯示文件、下載網絡文件等,這是單線程應用程序無法完成的。目前,支持多線程的開發工具主要有:Java、VC、Delphi和C++Builder。 多線程強調的是一個進程內部有多個流程在同時執行,同時執行的概念相當於PB分佈式計算中的異步處理。也就是說,只要我們在一個程序內部實現了異步處理,就相當於實現了多線程。分析至此,下一步該怎麼做就不言而喻了:在一個應用程序內部實現分佈式計算,使用服務器推送技術,異步執行共享對象中的函數。 下面就編寫一個Demo,介紹在PB中如何利用分佈式計算技術來開發多線程應用程序,其程序結構如圖1所示。uo—thread1和uo—thread2是類用戶對象uo—thread的兩個實例,uo—thread的功能是給實例變量li—Count自加5秒,自加的同時向中間對象uo—argv1和uo—argv2發送ue—thread消息。兩個中間對象的功能是把ue—thread消息轉化爲ue—thread1和ue—thread2後發給主窗口w—main。 圖1 程序結構 主窗口接收到ue—thread1消息後,顯示uo—thread1中自加變量的值,接收到ue—thread2後,顯示uo—thread2中自加變量的值。在單線程中,uo—thread1先執行,5秒鐘後uo—thread2開始執行,因此,前5秒內主窗口只能收到ue—thread1消息,後5秒內只能收到ue—thread2消息。在多線程中,uo—thread1和uo—thread2同時執行,因此w—main可以不斷地收到ue—thread1和ue—thread2消息。 1.設計用戶對象uo—thread 新建一個類用戶對象,命名爲uo—thread,添加如下兩個實例變量: NonVisualObject inv—arg Long li—Count //自加變量 創建如下三個用戶函數: ⑴uf—start(),功能是:完成自加5秒並向中間對象發送ue—thread消息。腳本爲: Time t0 t0= Now() //獲取當前時間 Do While SecondsAfter(t0,Now())〈=5 li—Count++//實例變量自加5秒 inv—arg.TriggerEvent(′ue—thread′) //向中間對象發送ue—thread消息 Loop ⑵uf—getcount(),功能是:獲取自加變量的瞬間值。其腳本爲: Return li—Count //返回實例變量 ⑶uf—setparent(NonVisualObject nv—arg),調用時,使用中間對象爲參數。腳本爲: inv—arg=nv—arg //用中間對象給實例變量賦值 2.設計中間對象uo—argv1和uo—argv2 新建一個類用戶對象,命名爲uo—argv1,添加如下實例變量: Window win—arg 創建用戶函數uf—setparent(Window w—argv),調用時,用主窗口作爲參數。其腳本爲: win—arg=w—argv //用主窗口對象給實例變量賦值 聲明用戶事件ue—thread,用於對uo—thread1發出的uo—thread消息進行響應,其腳本爲: win—arg.TriggerEvent(″ue—thread1″) //向主窗口發送ue—thread1消息 uo—argv2和uo—argv1完全一樣,只需將uo—argv1中的ue—thread1改爲uo—thread2即可。 3.設計主窗口w—main 主窗口外觀如圖2所示,凹下的三個控件分別爲:st—thread1、st—thread2、st—time,分別用於顯示uo—thread1和uo—thread2中自加變量的當前瞬間值和系統時間。聲明兩個用戶事件:ue—thread1和ue—thread2,分別用於對中間對象發送來的ue—thread1和ue—thread2消息進行響應。ue—thread1事件處理代碼爲: 圖2 主窗口 st—thread1.Text=String(uo—thread1.uf—getcount()) ue—thread2事件的處理代碼爲: st—thread2.Text=String(uo—thread2.uf—getcount()) w—main的Open事件代碼爲: uo—arg1 = Create uo—argv1 //初始化中間對象的一個實例 uo—arg2 = Create uo—argv2 uo—arg1.uf—setParent(This) //給中間對象的實例變量賦值 uo—arg2.uf—setParent(This) Timer(1) //啓動定時器 Timer事件處理代碼爲: st—time.Text=String(Now())//顯示當前時間 在“單線程”的Clicked事件中加入下列代碼: SharedObjectUnRegister(″object1″) //註銷先前註冊過的共享對象object1 SharedObjectUnRegister(″object2″) //註銷先前註冊過的共享對象object2 If IsValid(uo—thread1) Then Destroy uo—thread1 //若uo—thread1已經存在,先刪除 If IsValid(uo—thread2) Then Destroy uo—thread2 uo—thread1=Create uo—thread //初始化uo—thread1 uo—thread2=Create uo—thread uo—thread1.uf—setparent(uo—argv1) //用中間對象給uo—thread1中的實例變量賦值 uo—thread2.uf—setparent(uo—argv2) uo—thread1.Post uf—start() //執行uo—thread1中的uf—start()函數,完成後才執行下一句 uo—thread2.Post uf—start() //上一條語句執行完成後纔會執行 在“多線程”的Clicked事件中加入下列代碼: SharedObjectRegister(″uo—thread″,″object1″) //將uo—thread對象註冊爲object1 SharedObjectRegister(″uo—thread″,″object2″) //將uo—thread對象註冊爲object2 SharedObjectGet(″object1″,uo—thread1) //用uo—thread1引用共享對象object1 SharedObjectGet(″object2″,uo—thread2) //用uo_thread2引用共享對象object2 uo—thread1.uf—setparent(uo—argv1) //用中間對象給uo—thread1中的實例變量賦值 uo—thread2.uf—setparent(uo—argv2) uo—thread1.Post uf—start() //利用服務器推送技術,異步調用共享對象中的uf—start() uo—thread2.Post uf—start()//相當於啓動線程 4.執行 執行程序後,圖2就是點擊“多線程”後執行的一瞬間 |