Rotina em Segundo Plano - Thread

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

Moderador: Moderadores

cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano - Thread

Mensagem por cjp »

Uma dúvida: thread só funciona na minigui? Eu uso modo console; é possível usar thread?
Editado pela última vez por Toledo em 28 Mar 2017 08:49, em um total de 1 vez.
Razão: O presente tópico foi dividido de um outro tópico da seção MiniGui, uma vez que seu conteúdo não tem relação com os objetivos daquela seção, onde só podem constar dúvidas técnicas de programação diretamente relacionadas com a MiniGui.
Inacio de Carvalho Neto
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

Rotina em Segundo Plano

Mensagem por fladimir »

Sim é possível
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Tem como vc me ensinar a fazer isso, ou me passar algum link onde ensina? Eu nunca usei e não faço ideia de como começar. Já li alguma coisa aqui, mas sempre voltado à Minigui.
Inacio de Carvalho Neto
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

Rotina em Segundo Plano

Mensagem por fladimir »

Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Testei e funcionou.

Mas, sinceramente, acho que ainda não entendi a ideia.

Pensei que a ideia da thread seria a rotina ficar rodando em segundo plano, sem aparecer na tela. Não é isso? Pelo menos não é isso que está acontecendo no caso aqui. Ele simplesmente desviou para a função que era pra ficar rodando em segundo plano, aparecendo normalmente na tela.

Em suma, não entendi qual a diferença para uma chamada normal da função, nem qual a vantagem dessa aplicação.

Poderia me explicar, por favor?
Inacio de Carvalho Neto
Claudio Soto
Colaborador
Colaborador
Mensagens: 566
Registrado em: 27 Ago 2012 12:31
Localização: Uruguay
Contato:

Rotina em Segundo Plano

Mensagem por Claudio Soto »

Este talvez sea un ejemplo más claro:

Código: Selecionar todos

// Multi-Thread Demo WITH INHERIT PUBLIC vars, contrib by Roberto Lopez, March 2017

// NOTE: This is a classic ( conventional ) way how to use Multi-Thread at level of the OS, share ( inherit ) public and static vars

#include <hmg.ch>
#include "hbthread.ch"

FUNCTION Main

aThread := { NIL, NIL }

IF !hb_mtvm()
   MSGSTOP("There is no support for multi-threading")
   QUIT
ENDIF

DEFINE WINDOW Form_1 AT 301 , 503 WIDTH 550 HEIGHT 350 MAIN

    DEFINE BUTTON Button_1
        ROW    10
        COL    10
        WIDTH  160
        HEIGHT 28
        ACTION ( aThread[ 1 ] := hb_threadStart( HB_THREAD_INHERIT_PUBLIC , @Show_Time() ) )
        CAPTION "Start Clock Thread"
    END BUTTON

    DEFINE BUTTON Button_2
        ROW    50
        COL    10
        WIDTH  160
        HEIGHT 28
        ACTION ( aThread[ 2 ] := hb_threadStart( HB_THREAD_INHERIT_PUBLIC , @Show_Progress() ) )
        CAPTION "Start ProgressBar Thread"
    END BUTTON

    DEFINE LABEL Label_1
        ROW    10
        COL    360
        WIDTH  120
        HEIGHT 24
        VALUE "Clock Here!"
    END LABEL

    DEFINE PROGRESSBAR ProgressBar_1
        ROW    250
        COL    360
        WIDTH  150
        HEIGHT 30
        RANGEMIN 1
        RANGEMAX 10
        VALUE 0
    END PROGRESSBAR

    DEFINE BUTTON Button_3
        ROW    170
        COL    140
        WIDTH  260
        HEIGHT 28
        ACTION button_3_action()
        CAPTION "UI Still Responding to User Events!!!"
    END BUTTON

    DEFINE BUTTON Button_4
        ROW    250
        COL    10
        WIDTH  160
        HEIGHT 28
        ACTION button_4_action()
        CAPTION "Terminate all Threads"
    END BUTTON
    
END WINDOW

Form_1.Center
Form_1.Activate

Return


FUNCTION Show_Time()
   Form_1.button_1.enabled := .F. // disable 'Start Thread' button to avoid accidentally start a new thread!
   DO WHILE .T.   // thread infinite loop
      Form_1.label_1.value := Time()
      hb_idleSleep( .5 )
   ENDDO
RETURN nil


FUNCTION Show_Progress()
   Form_1.button_2.enabled := .F. //  disable 'Start Progress' button to avoid accidentally start a new thread!
   DO WHILE .T.   // thread infinite loop
      nValue := Form_1.progressBar_1.value
      nValue ++
      if nValue > 10
         nValue := 1
      endif
      Form_1.progressBar_1.value := nValue
      hb_idleSleep( .5 )
   ENDDO
RETURN nil


FUNCTION button_3_action
   MSGINFO('Clock and ProgressBar keep updating even the main thread is stopped at this MsgInfo!!!')
Return Nil


FUNCTION button_4_action
LOCAL i
   FOR i := 1 TO HMG_LEN( aThread ) 
      IF aThread[ i ] <> NIL
         hb_threadDetach( aThread[ i ] )   // close thread handle
         hb_threadQuitRequest( aThread[ i ] )   // terminate thread
         aThread[ i ] := NIL
      ENDIF
   NEXT
   Form_1.progressBar_1.value := 0
   Form_1.label_1.value := "Clock Here!"

   Form_1.button_1.enabled := .T.
   Form_1.button_2.enabled := .T.
Return Nil

Saludos.
Dr. Claudio Soto
(Uruguay)
http://srvet.blogspot.com
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina em Segundo Plano

Mensagem por JoséQuintas »

Talvez com GTWVG fique mais claro isso.
Pode ou não ter tela.

Código: Selecionar todos

PROCEDURE Main

   hb_ThreadStart( { || Teste() } )
   hb_ThreadStart( { || Teste() } )
   hb_ThreadWaitForAll()

   RETURN

FUNCTION Teste()

   hb_gtReload( "WVG" )
   cVar := Space(10)

   SetMode( 25, 80 )
   CLS
   @ 2, 20 SAY "teste" GET cVar
   READ

   RETURN NIL
Na prática vão ter TRES rotinas.
A principal, invisível, e mais duas com tela, totalmente independentes.

IMPORTANTÍSSIMO:
Na thread pode ser necessário configurar SET DATE, RddSetDefault(), etc.
É realmente como se fosse um programa em separado.
Mas se a Main() encerrar, todas as threads se encerram, por isso o uso de hb_ThreadWaitForAll().

E por último:
A janela GTWVG pode ser útil mesmo com outras GUIs, podendo ser usada invisível.
Não sei se isso permitiria usar o debug normal do Harbour em ambiente GUI...
Mas se misturar multithread nisso... talvez desse.... rs
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/
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Quintas, teu exemplo não funcionou aqui. Ele compila e teoricamente roda, mas não acontece nada; não aparece tela alguma, e aparentemente nem executa a function teste().

Claudio, ainda vou testar o teu exemplo.
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina em Segundo Plano

Mensagem por JoséQuintas »

Importante também na compilação:

HBMK2 test -mt gtwvg.hbc

o -mt indica multithread.
test.png
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/
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Ah, sim, agora funcionou.

Mas, ao colocar na minha aplicação, está dando erro de variável us inexistente, embora a variável us esteja predefinida como public.

Como faço para a thread ficar invisível?

Outra coisa: em testes feitos num passado já distante de tela oculta (não era com thread, e acho que era no xharbour), quando dava erro na tela oculta, a tela principal travava. Isso ocorre também com thread?
Inacio de Carvalho Neto
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Mais uma coisa, por favor: usando a gtwvg, mesmo sem usar a thread, minha tela ficou cortada. Veja o anexo.

Além disso, quando abro o programa, mesmo a tela principal abre numa segunda tela, ficando a primeira tela toda preta. Por que isso?
Anexos
Tela.png
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina em Segundo Plano

Mensagem por JoséQuintas »

Pra deixar GTWVG como default:

Código: Selecionar todos

PROCEDURE hb_GTSYS()

   REQUEST HB_GT_WVG_DEFAULT

   RETURN
Provavelmente tem mais a GT console por detrás.

E não precisa hb_gtReload("WVG"), isso é só pra thread adicional ter janela adicional

Em multithread, o default é que variáveis não são passadas pras threads, nem mesmo as públicas.
Caso precise disso, a opção é usar parâmetros.

Por exemplo:

Código: Selecionar todos

// Inherit copy of public
// hb_threadJoin( hb_threadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_MEMVARS_COPY ), @thFunc() ) )

// ? "Inherit copy of privates."
// hb_threadJoin( hb_threadStart( HB_BITOR( HB_THREAD_INHERIT_PRIVATE, HB_THREAD_MEMVARS_COPY ), @thFunc() ) )

// ? "Inherit copy of publics and privates."
// hb_threadJoin( hb_threadStart( HB_BITOR( HB_THREAD_INHERIT_MEMVARS, HB_THREAD_MEMVARS_COPY ), @thFunc() ) )

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/
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Rotina em Segundo Plano

Mensagem por cjp »

Não deu certo.

Fiz assim:

Código: Selecionar todos

function main
  hb_ThreadStart( { || Teste("I","Inacio","25/03/17","comin") } )
  hb_ThreadWaitForAll()

   REQUEST HB_GT_WVG_DEFAULT
...
return

FUNCTION Teste()
         parameters us, nmus, vers, seis

   cVar := Space(10)
         cadativ("Teste","Teste: início"," ",0,us,0,0," ")

   SetMode( 25, 80 )
   CLS
   @ 2, 20 SAY "teste" GET cVar
   READ

   RETURN NIL

Travou tudo no início.
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina em Segundo Plano

Mensagem por JoséQuintas »

Confundiu tudo.

Código: Selecionar todos

PROCEDURE Main

 hb_ThreadStart( { || Teste() } )
 hb_ThreadStart( { || Teste() } )
 hb_ThreadWaitForAll()

 RETURN

FUNCTION Teste()

 hb_gtReload( "WVG" )
 cVar := Space(10)

 SetMode( 25, 80 )
 CLS
 @ 2, 20 SAY "teste" GET cVar
 READ

 RETURN NIL

PROCEDURE hb_GTSYS()

 REQUEST HB_GT_WVG_DEFAULT

 RETURN
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

Rotina em Segundo Plano

Mensagem por JoséQuintas »

Ou vamos em partes:

definir GTWVG como default, exatamente deste jeito, sem mudanças.

Código: Selecionar todos

PROCEDURE hb_GTSYS()

 REQUEST HB_GT_WVG_DEFAULT

 RETURN
uma sub-rotina pra ter tela isolada da principal

Código: Selecionar todos

FUNCTION Teste()

 hb_gtReload( "WVG" ) // isto gera tela isolada, com tela/teclado próprio
 cVar := Space(10)

 SetMode( 25, 80 )
 CLS
 @ 2, 20 SAY "teste" GET cVar
 READ

 RETURN NIL
E rotina principal, sem tela, aguardando as threads encerrarem

Código: Selecionar todos

PROCEDURE Main

 hb_ThreadStart( { || Teste() } )
 hb_ThreadStart( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_MEMVARS_COPY, { || Teste() } ) // variáveis públicas visíveis na thread
 hb_ThreadWaitForAll()

 RETURN
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/
Responder