Duvida sobre Thread (Hb_ThreadStart)

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Tenho esse teste com uma Thread usando os parâmetros HB_BITOR

A função recebe lContinua .T., funciona.

Mas se eu quiser trocar o valor para lContinua := .F., a Thread continua com o valor da variável lContinua com .T.
Tem como intervir nos valores em uma thread?

no DO WHILE lContinua


Código: Selecionar todos

PUBLIC lContinua := .T.

        nThread := Hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ;
                                             HB_THREAD_INHERIT_PRIVATE, ;
                                             HB_THREAD_INHERIT_MEMVARS, ;
                                             HB_THREAD_MEMVARS_COPY ), ;
                                   { ||  Teste() } ) 

lContInua := .F.                                   

FUNCTION Teste()
LOCAL nRow AS NUMERIC, nCol AS NUMERIC

   nCol := Col()
   nRow := Row()
   
   nSeconds := Seconds()
   
   DO WHILE lContinua
   
      Hb_IdleSleep( 1 )

      IF (Seconds() - nSeconds) > 5
         nSeconds := Seconds()
         cTime := Time()
         IF File( "TIME.TXT" )
            cTime := Hb_MemoRead( "TIME.TXT" ) + Hb_Eol() + cTime
         ENDIF
         Hb_MemoWrit( "TIME.TXT" , cTime )
      ENDIF   
      hwg_DoEvents()
   ENDDO
   
   WAPI_BRINGWINDOWTOTOP( Hb_gtInfo( HB_GTI_WINHANDLE ) )
   
   Quit   

RETURN Nil
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

Não, só se for PUBLIC.

Uma opção é criar classe e/ou função.

Código: Selecionar todos

FUNCTION AppUserName( cValue )

   STATIC cAppUserName := ""

   IF cValue != Nil
      cAppUserName := cValue
   ENDIF

   RETURN cAppUserName
Desse jeito, usa AppUserName(), ou AppUserName( "JOSE" ), tanto faz a thread.
Acaba sendo bom, porque a compilação vai avisar se escrever errado.

Também pode ser array.
Classe... não é tão bom, porque não vai ter checagem de nome errado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

Veja se é uma coisa parecida com esta que está querendo:

Código: Selecionar todos

CREATE CLASS RunWhileThreadClass

   VAR lExit        INIT .F.
   VAR nThreadId
   VAR nInterval    INIT 600
   VAR cWindowTitle INIT ""
   VAR bCode
   METHOD New()     INLINE ::nThreadId := hb_ThreadSelf(), SELF
   METHOD Execute( bCode )

   ENDCLASS

METHOD Execute( bCode ) CLASS RunWhileThreadClass

   LOCAL nCont

   hb_gtReload( "WVG" )
   IF bCode != NIL
      ::bCode := bCode
   ENDIF
   AppInitSets()
   HB_GtInfo( HB_GTI_WINTITLE, ::cWindowTitle )
   wvgSetAppWindow():Hide()
   DO WHILE ! ::lExit
      Eval( ::bCode )
      FOR nCont = 1 TO ::nInterval
         hb_ReleaseCPU()
         IF hb_ThreadWait( ::nThreadId, 0.1, .T. ) == 1
            ::lExit := .T.
         ENDIF
         Inkey(1)
         IF ::lExit
            EXIT
         ENDIF
      NEXT
   ENDDO

   RETURN NIL
O que isso faz?
a thread vai ficar rodando, enquanto a thread que a chamou continuar ativa.
Opcionalmente, se alterar lExit := .T. ela encerra assim que possível.

Exemplo:

Código: Selecionar todos

oClasse := RunWHileThreadClass():New()
oClasse:bCode := { || Any() }
hbThreadStart( { || oClasse:Execute() } )
...
oClasse:lExit := .T.
Usei isso, por exemplo, em pedidos.
Enquanto o usuário estava na digitação de pedidos, aparecia alerta avisando de atrasos.
Saiu de pedidos, a rotina também encerrava automático. (nesse caso não precisava oClasse:lExit := .T.)

E qualquer coisa da classe, fica visível de qualquer thread.
São assim os controles Windows/GUI, só pra curiosidade.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

O cuidado com threads sobre compartilhar variáveis é grande.

Imagine o usuário num relatório escolhendo impressora, e em outro lugar também escolhendo impressora.
Se a variável for pública, um relatório vai alterar a impressora do outro.

Outro caso, um array:
Uma thread tá trabalhando com o array de um tamanho, e a outra thread altera esse tamanho.
E não só array, de repente uma string de tamanho 30 vira tamanho 10... se for no momento exato de pegar o conteúdo, o estrago pode ser grande, porque invade área da memória que não pertence à variável.
Nessas situações é onde precisa um cuidado a mais, o tal Mutex() que seria parecido com RLock(), mas pra variáveis.
Isso evita que o conteúdo seja alterado por outra thread durante o uso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

QUintas,

Entendi isso é muito pontual, enfim valeu pela dica
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Quintas,

faltou a função AppInitSets()
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

asimoes escreveu:faltou a função AppInitSets()
Uso essa pra configurar meu default.
Em thread precisa configurar RDDSetDefault(), SET DATE, e outras coisas, como se fosse outro EXE.
Então só criar com os seus defaults.

Nota: Usei um nome que achei adequeado, inicia os "sets" do aplicativo, por isso chamei AppInitSets()
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Quintas,

Aproveitando parte da sua classe, consegui simular o que eu queria debugando pra saber o conteúdo do arquivo time.txt
A função teste recebeu a troca da variável lExit depois de executada

Código: Selecionar todos

CREATE CLASS RunWhileThreadClass

   VAR lExit        INIT .F.
   METHOD New()     INLINE SELF CONSTRUCTOR 

   ENDCLASS
   PUBLIC oClasse := RunWHileThreadClass():New()

        nThread := Hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ;
                                             HB_THREAD_INHERIT_PRIVATE, ;
                                             HB_THREAD_INHERIT_MEMVARS, ;
                                             HB_THREAD_MEMVARS_COPY ), ;
                                             { || Teste() } ) 

   Inkey(0)
   
   oClasse:lExit := .T.       
   

FUNCTION Teste()
LOCAL nRow AS NUMERIC, nCol AS NUMERIC

   nSeconds := Seconds()
      
   DO WHILE ! oClasse:lExit
   
      Hb_IdleSleep( .1 )

      IF (Seconds() - nSeconds) > 5
         nSeconds := Seconds()
         cTime := Time()
         IF File( "TIME.TXT" )
            cTime := Hb_MemoRead( "TIME.TXT" ) + Hb_Eol() + cTime
         ENDIF
         Hb_MemoWrit( "TIME.TXT" , cTime )
      ENDIF   
      hwg_DoEvents()
   ENDDO

   Quit   

RETURN Nil
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

Só um comentário:

Porque não uma janela executando alguma coisa?
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

JoséQuintas escreveu:Só um comentário:

Porque não uma janela executando alguma coisa?
O meu teste é conseguir debugar o sistema enquanto a thread está sendo executada, dessa forma eu consigo debugar enquanto a thread está rodando e atribuir oClasse:lExit := .T. a qualquer momento no meu teste por fora da thread para interromper a sua execução, nesse teste eu não preciso de janela na thread

O interessante não sei se é uma limitação ou falha só consegui interromper a thread com uma variável de classe, uma variável publica tipo public lExit := .F. e depois de executada a thread modificando para lExit para .f. , não funciona, somente com variável da classe
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por JoséQuintas »

Se é só por causa da variável, usa a outra opção.

Código: Selecionar todos

FUNCTION AbortRun( lAbort )

   STATIC sAbort := .F.

   IF lAbort != Nil .AND. lAbort
      sAbort := .T.
   ENDIF

   RETURN sAbort
Na rotina:

Código: Selecionar todos

DO WHILE .T.
   IF AbortRun()
      EXIT
   ENDIF
ENDDO
E quando precisar:

Código: Selecionar todos

AbortRun( .F. )
hb_thread(...)
...
AbortRun( .T. )
A não ser que vão ter várias situações diferentes ao mesmo tempo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Quintas,

A sua alternativa também resolver, vlw
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Aquintas,

Não funcionou

Troquei o oClasse:lExit no while por AbortRun()

Antes da chamada da Thread

AbortRun( .F. )

DO WHILE ! AbortRun() //oClasse:lExit

Depois da chamada da Thread AbortRun( .T. )

O loop da Thread continuou rodando, só funciona com oClasse:lExit
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por asimoes »

Completando:

Assim funciona, usando a função AbortRun() não

Código: Selecionar todos

  oClasse:lExit := .F.
 
   fErase( "TIME.TXT" )
   
         nThread := Hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ;
                                              HB_THREAD_INHERIT_PRIVATE, ;
                                              HB_THREAD_INHERIT_MEMVARS, ;
                                              HB_THREAD_MEMVARS_COPY ), ;
                                              { || Teste() } ) 
                                       
   altd()
   
   oClasse:lExit := .T.
13:35:06
13:35:11
13:35:16
FIM

O FIM siginifica que saiu do while
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Claudio Soto
Colaborador
Colaborador
Mensagens: 566
Registrado em: 27 Ago 2012 12:31
Localização: Uruguay
Contato:

Duvida sobre Thread (Hb_ThreadStart)

Mensagem por Claudio Soto »

Alexandre probá sin el parámetro HB_THREAD_MEMVARS_COPY

Porque si mal no recuerdo HB_THREAD_MEMVARS_COPY envía una copia de la variable (paso por valor) y no la variable en sí (paso por referencia)
Saludos.
Dr. Claudio Soto
(Uruguay)
http://srvet.blogspot.com
Responder