Re: HMG and Multi-Threading
Posted: Mon Nov 14, 2016 9:56 am
Thanks for this info!
Exclusive forum for HMG, a Free / Open Source xBase WIN32/64 Bits / GUI Development System
http://www.hmgforum.com/
Very interesting matter. Thank you maestro Roberto to come up with this matter and idea.KDJ wrote: ↑Tue Nov 08, 2016 6:48 pm Roberto Lopez, thank you very much for the example of multi-threading.
On the basis of your code, I want to show how to:
- terminate new thread from main thread - hb_threadQuitRequest(nThreadClock),
- notify main thread about child thread completion - PostMessage(Main.HANDLE, WM_APP, 0, 0),
- receive value returned from function completed in another thread - hb_threadJoin(nThreadClock, @cTime).
Code: Select all
#include <hmg.ch> #define HB_THREAD_INHERIT_PUBLIC 1 #define WM_APP 0x8000 Function Main DEFINE WINDOW Main AT 301 , 503 WIDTH 550 HEIGHT 350 VIRTUAL WIDTH Nil VIRTUAL HEIGHT Nil TITLE "" ICON NIL MAIN CURSOR NIL ON INIT Nil ON RELEASE Nil ON INTERACTIVECLOSE Nil ON MOUSECLICK Nil ON MOUSEDRAG Nil ON MOUSEMOVE Nil ON SIZE Nil ON MAXIMIZE Nil ON MINIMIZE Nil ON PAINT Nil BACKCOLOR Nil NOTIFYICON NIL NOTIFYTOOLTIP NIL ON NOTIFYCLICK Nil ON GOTFOCUS Nil ON LOSTFOCUS Nil ON SCROLLUP Nil ON SCROLLDOWN Nil ON SCROLLLEFT Nil ON SCROLLRIGHT Nil ON HSCROLLBOX Nil ON VSCROLLBOX Nil DEFINE BUTTON Button_1 ROW 10 COL 10 WIDTH 160 HEIGHT 28 ACTION main_button_1_action() CAPTION "Start Clock Thread" FONTNAME "Arial" FONTSIZE 9 END BUTTON DEFINE BUTTON Button_2 ROW 50 COL 10 WIDTH 160 HEIGHT 28 ACTION main_button_2_action() CAPTION "Start ProgressBar Thread" FONTNAME "Arial" FONTSIZE 9 END BUTTON DEFINE BUTTON Button_3 ROW 170 COL 140 WIDTH 260 HEIGHT 28 ACTION main_button_3_action() CAPTION "UI Still Responding to User Events!!!" FONTNAME "Arial" FONTSIZE 9 END BUTTON DEFINE LABEL Label_1 ROW 10 COL 360 WIDTH 120 HEIGHT 24 VALUE "Clock Here!" FONTNAME "Arial" FONTSIZE 9 END LABEL DEFINE LABEL Label_2 ROW 10 COL 180 WIDTH 150 HEIGHT 30 VALUE "" FONTNAME "Arial" FONTSIZE 9 END LABEL DEFINE PROGRESSBAR ProgressBar_1 ROW 50 COL 360 WIDTH 150 HEIGHT 30 RANGEMIN 1 RANGEMAX 10 VALUE 0 END PROGRESSBAR ON KEY ESCAPE ACTION Main.RELEASE END WINDOW EventCreate('Show_Time_Completed', Main.HANDLE, WM_APP) Main.Center Main.Activate Return FUNCTION Show_Time_Completed() hb_idleSleep(0.05) main_button_1_action() RETURN NIL FUNCTION Show_Time() LOCAL nTimeStart := Seconds() LOCAL nTime := nTimeStart LOCAL nHour LOCAL nMinute LOCAL nSecond LOCAL cTime DO WHILE (nTime - nTimeStart) < 5 nTime := Seconds() nHour := Int(nTime / 3600) nSecond := nTime % 3600 nMinute := Int(nSecond / 60) nSecond := nSecond % 60 cTime := PadL(nHour, 2, '0') + ':' + PadL(nMinute, 2, '0') + ':' + PadL(nSecond, 5, '0') main.label_1.value := cTime hb_idleSleep(0.01) ENDDO PostMessage(Main.HANDLE, WM_APP, 0, 0) RETURN cTime FUNCTION Show_Progress() LOCAL nValue DO WHILE .T. nValue := main.progressBar_1.value nValue ++ if nValue > 10 nValue := 1 endif main.progressBar_1.value := nValue hb_idleSleep(0.25) ENDDO RETURN nil Function main_button_1_action STATIC nThreadClock LOCAL cTime IF !hb_mtvm() MSGSTOP("There is no support for multi-threading, clocks will not be seen.") Return Nil ENDIF IF ValType(nThreadClock) == 'U' nThreadClock := hb_threadStart(HB_THREAD_INHERIT_PUBLIC , @Show_Time()) Main.Button_1.CAPTION := 'Stop Clock Thread' Main.Button_1.FONTBOLD := .T. Main.Label_1.FONTBOLD := .T. Main.Label_2.VALUE := "Clock Thread will be completed after 5 seconds" ELSE Main.Button_1.CAPTION := 'Start Clock Thread' Main.Button_1.FONTBOLD := .F. Main.Label_1.FONTBOLD := .F. Main.Label_2.VALUE := "" IF hb_threadQuitRequest(nThreadClock) //MsgBox('Clock Thread has been terminated.') ELSEIF hb_threadJoin(nThreadClock, @cTime) MsgBox('Clock Thread has been completed at ' + cTime) ENDIF nThreadClock := NIL ENDIF Return Nil Function main_button_2_action STATIC nThreadProgress IF !hb_mtvm() MSGSTOP("There is no support for multi-threading, clocks will not be seen.") Return Nil ENDIF IF ValType(nThreadProgress) == 'U' nThreadProgress := hb_threadStart(HB_THREAD_INHERIT_PUBLIC, @Show_Progress()) Main.Button_2.CAPTION := 'Stop ProgressBar Thread' Main.Button_2.FONTBOLD := .T. ELSE IF hb_threadQuitRequest(nThreadProgress) nThreadProgress := NIL Main.Button_2.CAPTION := 'Start ProgressBar Thread' Main.Button_2.FONTBOLD := .F. ENDIF ENDIF Return Nil Function main_button_3_action MSGINFO('Clock and ProgressBar keep updating even the main thread is stopped at this MsgInfo!!!') Return Nil
Entiendo pues que para trabajar en una multitarea y poder tener varias ventanas con el mismo proceso abierto sería una buena posiblidad, ya que cada hb_threadStart asigna un ambito Estoy en lo cierto.Ah, y otra cosa súper interesante , y es que el ámbito de una tabla dbf abierta, pertenece en el hilo que se abrió, usando el mismo alias en hilos separados.
Esto, a la hora de portar código existente , como el caso anteriormente explicado, nos ahorra horas y horas de portabilidad de un sistema monolítico a un sistema con threads.