Rotina em Segundo Plano
Enviado: 28 Mar 2017 13:02
Eu uso HB_THREAD_INHERIT_MEMVARS, o que me chamou atenção foi HB_THREAD_MEMVARS_COPY, por isso questionei o que é cada tipo
Ahora , también a la hora de crear un thread , podemos definir la visibilidad de las variables
dentro del hilo. Fichero hbthread.ch
#define HB_THREAD_INHERIT_PUBLIC 1
Indica que las variables públicas son compartidas por todos los hilos
#define HB_THREAD_INHERIT_PRIVATE 2
Indica que las variables privadas son compartidas por todos los hilos
#define HB_THREAD_INHERIT_MEMVARS 3
Indica que las variables privadas y públicas son compartidas por todos los hilos
#define HB_THREAD_MEMVARS_COPY 4
Indica que lo que se envía es una copia , no la variable en sí.
hb_threadStart( HB_THREAD_INHERIT_PUBLIC, @Process(), Self ) )
otro ejemplo ;
hb_threadStart( HB_BITOR( HB_THREAD_INHERIT_MEMVARS + ;
HB_THREAD_MEMVARS_COPY ), ;
@thFunc() )
Se for o que estou pensando, pode ser interessante.De todas maneras, no sé exactamente cuál es el propósito del detach en Harbour si llamando a hb_threadStart() realiza la misma función, sin usar Join, al menos, en las pruebas
que he realizado no logro ver diferencias entre crear un hilo, y crear un hilo y dejarlo morir y llamar a detach. ( Si alguien lo sabe, bienvenida explicación )
Cuando se crea un thread el SO devuelve un handle que identifica al thread. Cuando el thread termina mientras no se cierra ese handle el SO mantiene en memoria información sobre ese thread. Lo que hace el detach es precisamente cerrar ese handle y en consecuencia permitir que el SO remueva la información de ese thread de la memoria cuando el thread termine.JoséQuintas escreveu:Achei curiosa esta parte
Explica como faz, só não sabe pra que serve... rs
http://xthefull.blogspot.com.br/2016/07 ... etach.html
Se for o que estou pensando, pode ser interessante.De todas maneras, no sé exactamente cuál es el propósito del detach en Harbour si llamando a hb_threadStart() realiza la misma función, sin usar Join, al menos, en las pruebas
que he realizado no logro ver diferencias entre crear un hilo, y crear un hilo y dejarlo morir y llamar a detach. ( Si alguien lo sabe, bienvenida explicación )
Precisa teste, mas só imagino que seja deixar a thread separada de Main(), como se fosse uma Main2()..
Se for isso, elimina o uso de hb_ThreadWaitForAll().
Código: Selecionar todos
nThread := hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ;
HB_THREAD_INHERIT_PRIVATE, ;
HB_THREAD_INHERIT_MEMVARS ), ;
{ || ::Download( "DROPBOX" + hb_PS() ) } )
::WaitThread( nThread )
METHOD WaitThread( nThread ) CLASS ClMonitor
DO WHILE .T.
IF hb_ThreadWait( nThread, 0.1, .T. ) == 1
EXIT
ENDIF
DO EVENTS
ENDDO
RETURN Nil
Código: Selecionar todos
PROCEDURE Main
hb_ThreadStart( { || teste() } )
hb_ThreadStart( { || teste() } )
hb_ThreadStart( { || teste() } )
hb_ThreadWaitForAll()
A nivel del SO el detach no tendría porque afectar hb_ThreadWaitForAll, pero como todas las funciones de hb son un wrappler para las funciones de thread a nivel de C, hb podría combinar varias funciones C en una función de hb, abría que ver como hb implementa en los fuentes.JoséQuintas escreveu:Eu usava assim antes, inclusive um array pra controlar várias threads.
hb_ThreadWaitForAll() já aguarda tudo de uma vez.
imagine sua rotina nesta situação:
A informacão do Dr Claudio Soto me deixou na dúvida sobre SEMPRE usar hb_ThreadDetach()Código: Selecionar todos
PROCEDURE Main hb_ThreadStart( { || teste() } ) hb_ThreadStart( { || teste() } ) hb_ThreadStart( { || teste() } ) hb_ThreadWaitForAll()
Não sei se afetaria o teste de hb_ThreadWaitForAll()
Também não sei que tipo de recurso é armazenado, se isso é muito ou pouco no contexto geral.
Cuidado con la combinación OR de Inherit, están definidos como:asimoes escreveu:Código: Selecionar todos
nThread := hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ; HB_THREAD_INHERIT_PRIVATE, ; HB_THREAD_INHERIT_MEMVARS ), ; { || ::Download( "DROPBOX" + hb_PS() ) } )
Código: Selecionar todos
#define HB_THREAD_INHERIT_PUBLIC 1 Binario 0001
#define HB_THREAD_INHERIT_PRIVATE 2 0010
#define HB_THREAD_INHERIT_MEMVARS 3 0011
#define HB_THREAD_MEMVARS_COPY 4 0100
Código: Selecionar todos
HB_BITOR( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE, HB_THREAD_INHERIT_MEMVARS )Código: Selecionar todos
HB_THREAD_INHERIT_PUBLIC + HB_THREAD_INHERIT_PRIVATE + HB_THREAD_INHERIT_MEMVARS Código: Selecionar todos
HB_THREAD_INHERIT_PRIVATE + HB_THREAD_INHERIT_MEMVARS|  COPY(4)  |  PRIVATE(2)  |  PUBLIC(1)  |  decimal  |  combinação  |
|  0  |  0  |  1  |  1  |  PUBLIC  |
|  0  |  1  |  0  |  2  |  PRIVATE  |
|  0  |  1  |  1  |  3  |  MEMVAR (PUBLIC + PRIVATE)  |
|  1  |  0  |  1  |  5  |  PUBLIC,COPY  |
|  1  |  1  |  0  |  6  |  PRIVATE,COPY  |
|  1  |  1  |  1  |  7  |  MEMVAR (PUBLIC=PRIVATE),COPY  |
Código: Selecionar todos
numero1[ 1 ] := .T.
numero1[ 2 ] := .T.
numero1[ 3 ] := .T.
numero2[ 1 ] := .T.
numero2[ 2 ] := .T.
numero2[ 3 ] := .T.
resultado[ 1 ] := numero1[ 1 ] .OR. numero2[ 1 ]
resultado[ 2 ] := numero1[ 2 ] .OR. numero2[ 2 ]
resultado[ 3 ] := numero1[ 3 ] .OR. numero2[ 3 ]
Código: Selecionar todos
FUNCTION MAIN()
nThread := hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ;
HB_THREAD_INHERIT_PRIVATE, ;
HB_THREAD_INHERIT_MEMVARS ), ;
{ || Teste() } )
//hb_ThreadWaitForAll()
WaitThread( nThread )
RETURN Nil
FUNCTION Teste()
LOCAL oCrt
oCrt := WvgCrt():New()
oCrt:lModal := .T.
oCrt:visible := .T.
oCrt:create()
oCrt:resizable := .F.
Hb_GTInfo( HB_GTI_WINTITLE, "Teste com Thread" )
FOR I:=1 TO 3000000
@ 0,0 SAY StrZero( I, 7 )
NEXT
oCrt:destroy()
RETURN Nil
FUNCTION WaitThread( nThread )
DO WHILE .T.
IF hb_ThreadWait( nThread, 0.1, .T. ) == 1
EXIT
ENDIF
Evento()
ENDDO
RETURN Nil
FUNCTION Evento()
hwg_DoEvents() /ou DoEvents()
RETURN .T.
Aunque sea en modo consola siempre se crea una ventana, en Windows todo es una ventana, un botón, un menú, un cuadro de diálogo, etc. y en consecuencia cada uno esta asociado a una cola de mensajes. Además si mal no recuerdo las gt crean ventanas de Windows.asimoes escreveu:Olá pessoal,
Usando hb_ThreadWaitForAll() e/ou WaitThread( nThread ) *
* função WaitThread listada abaixo
Vejam a mensagem no título da janela principal Teste Diversos (Não está respondendo)
Usando somente hb_ThreadWaitForAll() Usando a função WaitThread() -> hb_ThreadWait()
A função Evento() pode usar hwg_DoEvents() ou DoEvents() do Dr. Claudio (HMG) https://pctoledo.org/forum/viewto ... 6&start=15Código: Selecionar todos
FUNCTION MAIN() nThread := hb_ThreadStart( HB_BITOR( HB_THREAD_INHERIT_PUBLIC, ; HB_THREAD_INHERIT_PRIVATE, ; HB_THREAD_INHERIT_MEMVARS ), ; { || Teste() } ) //hb_ThreadWaitForAll() WaitThread( nThread ) RETURN Nil FUNCTION Teste() LOCAL oCrt oCrt := WvgCrt():New() oCrt:lModal := .T. oCrt:visible := .T. oCrt:create() oCrt:resizable := .F. Hb_GTInfo( HB_GTI_WINTITLE, "Teste com Thread" ) FOR I:=1 TO 3000000 @ 0,0 SAY StrZero( I, 7 ) NEXT oCrt:destroy() RETURN Nil FUNCTION WaitThread( nThread ) DO WHILE .T. IF hb_ThreadWait( nThread, 0.1, .T. ) == 1 EXIT ENDIF Evento() ENDDO RETURN Nil FUNCTION Evento() hwg_DoEvents() /ou DoEvents() RETURN .T.