Page 2 of 3

Re: HMG and Multi-Threading

Posted: Mon Jul 04, 2016 9:44 am
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

Re: HMG and Multi-Threading

Posted: Mon Jul 04, 2016 3:09 pm
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 6898 times

Re: HMG and Multi-Threading

Posted: Mon Jul 04, 2016 3:31 pm
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...

Re: HMG and Multi-Threading

Posted: Mon Jul 04, 2016 3:43 pm
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.

Re: HMG and Multi-Threading

Posted: Tue Nov 08, 2016 6:48 pm
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

Re: HMG and Multi-Threading

Posted: Tue Nov 08, 2016 11:54 pm
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!

Re: HMG and Multi-Threading

Posted: Wed Nov 09, 2016 1:47 pm
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

Re: HMG and Multi-Threading

Posted: Wed Nov 09, 2016 2:13 pm
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.

Re: HMG and Multi-Threading

Posted: Sat Nov 12, 2016 4:50 pm
by chrisjx2002
Hello,

Very interesting subject.

How to make public variables visible between threads?

Re: HMG and Multi-Threading

Posted: Sat Nov 12, 2016 10:02 pm
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 !!")