HMG and Multi-Threading

Discuss anything else that does not suite other forums.

Moderator: Rathinagiri

User avatar
serge_girard
Posts: 3165
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: HMG and Multi-Threading

Post by serge_girard »

Thanks Roberto,

At this moment I cannot imagine for what I can use it, or for which application.
But I think it has great potential in order to run batch processes at the same time as interactive processes.
I will think about it ...!

Serge
There's nothing you can do that can't be done...
User avatar
andyglezl
Posts: 1461
Joined: Fri Oct 26, 2012 7:58 pm
Location: Guadalajara Jalisco, MX
Contact:

Re: HMG and Multi-Threading

Post by andyglezl »

Hola

Estoy con un proyecto. (probando HMG 3.4.3) sobre la base del ejemplo que envié .
En donde tengo varios procesos corriendo a la vez con un timer, el cual me despliega la HORA, toca archivos MIDI y
checa cuando temina para iniciar otro, tener control de varios MENUS, checar el Spool de la impresora, ejecutar un archivo
batch mientras sigue lo demas. (No se si esto sea MULTI-THREADING pero funciona OK)
-----------------------------------------------------------------------------------------------------------------------------------------------------
Hello

I'm with a project. (HMG testing 3.4.3) on the basis of example I sent.
Where I have several processes running at the time with a timer, which displays my time, playing MIDI files
Conclude validated when to start another, have several MENUS control, check the printer spool, run a file
batch while the rest follows. (Do not know if this is multithreading but it works OK)

andyglezl wrote:
Hola Roberto
Quizá este ejemplo de ideas...
en la opción 7, tienes acceso al menu principal y al menu de la opion ejectada.
viewtopic.php?f=6&t=4468&p=42585&hilit= ... enu#p42585

Ejemplo.jpg
Ejemplo.jpg (339.91 KiB) Viewed 6069 times
Andrés González López
Desde Guadalajara, Jalisco. México.
User avatar
Roberto Lopez
HMG Founder
Posts: 4004
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMG and Multi-Threading

Post by Roberto Lopez »

andyglezl wrote: batch while the rest follows. (Do not know if this is multithreading but it works OK)
The main difference (among others equally important) is that your app will not continue until the timer procedure do not return control. So a timer procedure doing a long procedure could 'lock' your app. With multi-threading you have not that problem (in fact in my sample, the two threads created NEVER return control to the app).

Other important difference is that by deafult, a new thread has its own workareas and variables, so you can do anything as if you were executing a separate exe.

Imagine a timer that works with workareas... firing out of your control... really scaring!

I'm just learning about this (in fact... about everything :) ) so, could be a lot of other things to consider yet...
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
User avatar
Roberto Lopez
HMG Founder
Posts: 4004
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMG and Multi-Threading

Post by Roberto Lopez »

serge_girard wrote:Thanks Roberto,

At this moment I cannot imagine for what I can use it, or for which application.
But I think it has great potential in order to run batch processes at the same time as interactive processes.
I will think about it ...!

Serge
In my case a complex remote query executed at an internet connected server.

It can take a lot of time and since it is executed synchronously, my app is seen by the OS as 'not responding'.

In this case, multi-threading comes to rescue.

It could be useful in many other cases... ie, commands like SUM or SET FILTER that could take forever to execute on large shared tables.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
KDJ
Posts: 243
Joined: Mon Sep 05, 2016 3:04 am
Location: Poland

Re: HMG and Multi-Threading

Post by KDJ »

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
User avatar
Roberto Lopez
HMG Founder
Posts: 4004
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMG and Multi-Threading

Post by Roberto Lopez »

KDJ wrote: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).
<...>
Thanks!
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
EduardoLuis
Posts: 682
Joined: Tue Jun 04, 2013 6:33 pm
Location: Argentina

Re: HMG and Multi-Threading

Post by EduardoLuis »

Hi Roberto:

The above code, is what i use to show end user an app is working, so he can't imagine the system hangs.-
I have no experience on multi-threading, but i suppose this can give you another idea.-
I think that if is not possible to share between app or pass values between them, another solution is that threading app fills a variable and save to a .MEM file, and the other app (on DO WHILE instante) chek if .MEM file exist; if it's .T. stop loop.-

Please forgiveme is this idea is silly, but you nothing loose taking a look at it.-
With regards.
Eduardo

Code: Select all

PROCEDURE INTEGRADOR_LEGAL()

	DEFINE WINDOW GENERADOR ;
      AT 360, ctr + 745 ;
		WIDTH 230 HEIGHT 255 ;
		TITLE '' ;
      MODAL ;
      NOSIZE ;
      NOSYSMENU ;
      NOCAPTION ;
      BACKCOLOR { 255,255,255 } 

// REPLACE THIS LINES WITH THE GRAPHIC YOU WANT........      
//      DEFINE IMAGE LOGO_1
//         ROW	0
//         COL	0
//         WIDTH	230
//         HEIGHT 255
//         PICTURE 'GENPDF'
//         STRETCH	.T.
//      END IMAGE         

		DEFINE TIMER Timer_1 ;
		INTERVAL 1000 ;
		ACTION cheka_impreL()             

   END WINDOW 

   ACTIVATE WINDOW GENERADOR
      
RETURN      

PROCEDURE CHEKA_IMPREL
   pdf_createRO() // THIS GOES TO A ROUTINE THAT CREATES A BIG PDF
   pdf_createLO() // THIS GOES TO A ROUTINE THAT CREATES A BIG PDF
   DO WHILE TERMINADO == 'N' // TERMINADO IS A PUBLIC VARIABLE THAT IS FILLED WITH 'S" WHEN PDF_CREATE..  ENDS
   END DO
   GENERADOR.RELEASE
   terminado := 'N'
   EXECUTE file 'AVALES-ENDOSOS.pdf'
   EXECUTE file 'PAGARES.pdf' 
RETURN
User avatar
Roberto Lopez
HMG Founder
Posts: 4004
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMG and Multi-Threading

Post by Roberto Lopez »

EduardoLuis wrote:Hi Roberto:

The above code, is what i use to show end user an app is working, so he can't imagine the system hangs.-
I have no experience on multi-threading, but i suppose this can give you another idea.-
<...>
To use multi-thread with HMG, you must make public variables visible between threads, so, if you need communicate something, it should work without problems (no need for .mem).

Of course... you could avoid multi-threading using a lot of different (timer-based) techniques, so, it depends on your personal preferences and needs.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
chrisjx2002
Posts: 190
Joined: Wed Jan 06, 2010 5:39 pm

Re: HMG and Multi-Threading

Post by chrisjx2002 »

Hello,

Very interesting subject.

How to make public variables visible between threads?
User avatar
quartz565
Posts: 667
Joined: Mon Oct 01, 2012 12:37 pm
Location: Thessaloniki, Greece
Contact:

Re: HMG and Multi-Threading

Post by quartz565 »

chrisjx2002 wrote:Hello,

Very interesting subject.

How to make public variables visible between threads?
According to those already Roberto said:
We can call a function and send the variables we want by reference.
Τhe following work for us:

Code: Select all

 
#include "hmg.ch"
#define HB_THREAD_INHERIT_PUBLIC 1 

......
....... 
cSmsToCus := "Hello my friend! Thanks for your help..."
cTelNo := {+306948367796} 


HB_THREADSTART( HB_THREAD_INHERIT_PUBLIC, @SendSms(),@cSmsToCus, @cTelNo) 
 
 msginfo("The sms has already been sent !!")
Best Regards,
Nikos.

os: Windows Server 2019 - 64
Post Reply