Clipper On Line • Ver Tópico - StartThread()
Mudar para estilo Clássico
Projeto Harbour - Compilador de código aberto compatível com o Clipper.
Postar uma resposta

StartThread()

08 Mai 2020 14:02

Ola!
Fatal: Unable to open file 'RTLMT.LIB'

Faltou criar as Libs do Xhb com o "mt" no fnal das libs, tem que recompilar os fontes com essa opção.
É uma "flag" um parâmetro, não achei na internet.

Saudações,
Itamar M. Lins Jr.

StartThread()

08 Mai 2020 14:04

Já sei porque precisou do -gtwin.
O meu \xharbour\bin\hbmk.hbc está como GUI

Código:
d:\xharbour\bin>type hbmk.hbc
gui=yes
strip=yes
compr=yes

StartThread()

08 Mai 2020 14:12

Adicional pra quem for usar o hbmk2 no XHarbour:

aqui renomeei o hbmk2.exe pra xhbmk2.exe
e criei um hbmk2.bat

Código:
@echo off
if "%1" == "-find"     goto :find
if "%1" == "-doc"      goto :find
if "%1" == "-fullhelp" goto :find
if "%1" == "-help"     goto :find
xhbmk2 -xhb %*
goto :fim
:find
xhbmk2 %*
:fim


Tinha me esquecido disso.
Fiz assim pra facilitar quando for fazer algum teste.
A única diferença é ele acrescentar -xhb no comando do hbmk2.
O resto... é pra continuarem funcionando os outros comandos.
E pra quem não sabe, %* é pra indicar todos os parâmetros de uma vez.
Teria limite de 9 se eu indicasse %1 %2 %3 %4 %5 ...

StartThread()

08 Ago 2020 12:26

Bom dia pessoal.
Estou com o mesmo problema, preciso rodar uma função em segundo plano e não estou conseguindo.
Preciso dar um select no banco de dados sql e passar tudo para dbf para mostrar no dbedit, ou seja, rodar a pesquisa e gravar em dbf em segundo plano já com o dbedit aberto.

Exemplo abaixo busca cliente para pesquisar digitando
Código:

Function ChecaCli(a_SQL,aTipo,Lin,Col,Tam,FuncC)
Private NomeCampos,UnSelect:=Str(Select(),2)
Private wRow:=Row(),wCol:=Col()
a_SQL:=If(a_SQL=Nil,.F.,a_SQL)

If a_SQL=.T.  //é em sql a pesquisa
   a_Campos  :=FB_pegaEstrutura("TB_COLABORADOR") //pego os campos da tabela colaboradores
   oTempo_DBF:=HoraTmp() //nomeio um temporario
   OpenTmp(a_Campos,"NOME","&oTempo_DBF.",,,,,,,.F.) //crio o temporario vazio com a estrutura do TB_COLABORADOR
   DbSelectArea(oTempo_DBF) //seleciono o temporario
   DBF_CargaTH("TB_COLABORADOR","*","",a_Campos) //dou uma carga no temporario com tudo que tem em TB_COLABORADOR + de 6.000 registros (lento)
EndIf
   NomeCampos:=
                {{"codigo","Abreviate(nome,60)","venda","ShowSituacao(situacao)","RetVar()","RetRg()","Abreviate(endereco,30)","numero","e_mail","h_page","RP"},;
                {"@R 999999999","@!","@!","@!","@!","@!","@!","@!","@X","@X","@!"},;
                {"CÓDIGO","NOME DO CLIENTE","S","SITUAÇÃO ATUAL DO CLIENTE","CPF/CGC","RG/IEST","ENDEREÇO","NUMERO","EMAIL","HOMEPAGE","RP"}}
                o_MsgR:=" "
   NewDbBusca(04,00,,,"Clientes",NomeCampos,,o_MsgR,,,,,,.T.) // mostro em dbedit o conteudo do temporario no formato acima



Esta função serve só para chamar a modulo_carga em thread
Código:

Function DBF_CargaTH(oTabela,oPesquisa,oCondicao,oCampos)
Return pThread := hb_StartRead( Modulo_Carga(oTabela,oPesquisa,oCondicao,oCampos) ) //retornando assim da erro
Return pThread := hb_StartRead( {||  Modulo_Carga(oTabela,oPesquisa,oCondicao,oCampos) } ) //retornando assim nao da erro, mas retorna vazio
Return  Modulo_Carga(oTabela,oPesquisa,oCondicao,oCampos) //retornando assim, funciona mas demora, pq são 6.000 registros, por isto colocar em segundo plano, pq aí ele passaria para abrir o dbedit mesmo com poucos dados e iria inserindo enquanto seria pesquisado os clientes, algo assim.



Abaixo monta o banco de dados DBF para mostrar no dbedit
Código:
Static Function Modulo_Carga(oTabela,oPesquisa,oCondicao,oCampos)
Local i_m,i_l,oCampo,oDados

Local oSQL := DB_SQL_SELECT(oTabela,oPesquisa,oCondicao)

For i_m:= 2 To Len(oSQL) //todo registro começa da linha 2
    DbAppend()
    For i_l:= 1 To Len(oCampos)
        oCampo:=AllTrim(oCampos[i_l,1])
        oDados:=DB_SQL_Fields(oSQL,oCampo,i_m)
        Field->&oCampo. := oDados
    Next
Next
Return .T.


Obs: Não fiz em MATRIZ devido não ter conseguindo montar uma TBROWSE para funcionar genericamente com array, igual a dbedit com dbf, faria isto depois com tempo.

Se alguém souber como colocar em segundo plano em harbour, fico muito agradecido.

StartThread()

08 Ago 2020 15:26

Hola, probá así a ver si funciona:

Código:
hb_threadStart( hb_bitOr( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE), @Modulo_Carga(), oTabela, oPesquisa, oCondicao, oCampos )

StartThread()

10 Ago 2020 09:14

Bom dia
Testei mas desta forma continua parado aguardando terminar a busca dos dados para depois dar erro
"
Função.............: HB_THREADSTART
Gencode............: 1
Descrição..........: Argument error
"

nThreadId := hb_ThreadStart( hb_bitOr( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE), DBF_CargaTH("TB_COLABORADOR","*","",a_Campos) )

@DBF_CargaTH("TB_COLABORADOR","*","",a_Campos) Não funciona, da erro na compilação falando que "@" não pode ser usado.

Grato

StartThread()

10 Ago 2020 09:37

Hola,
El @ es para pasar la dirección de la función, es decir para pasar un puntero a la función.
En hb_startThread, los parámetros de la función a ser llamada van después del @ como parámetros de la función hb_startThread

StartThread()

10 Ago 2020 09:50

Hola,
Así seria la forma correcta de llamar tu función:

Código:
Function DBF_CargaTH(oTabela,oPesquisa,oCondicao,oCampos)
Return pThread := hb_threadStart( hb_bitOr( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE), @Modulo_Carga(), oTabela, oPesquisa, oCondicao, oCampos )

StartThread()

10 Ago 2020 17:48

Boa tarde Soto.
Eu não sabia deste macete, farei da forma que tu me passou e verei hoje a noite o que vai ocorrer.

Gracias.

StartThread()

10 Ago 2020 19:44

Chamou a atenção isto:

dou uma carga no temporario com tudo que tem em TB_COLABORADOR + de 6.000 registros (lento)
Local oSQL := DB_SQL_SELECT(oTabela,oPesquisa,oCondicao)


Multithread pra SQL porque 6.000 registros fica lento?
Só se fossem 6 milhões de registros ao invés de 6.000
Tem coisa muito errada nisso aí.

Veja aqui: 25.270 registros, todas as cidades do Brasil

http://www.pctoledo.com.br/forum/viewtopic.php?f=5&t=24468

StartThread()

10 Ago 2020 21:39

Faço assim.

Código:

nThread  :=  Hb_ThreadStart( Hb_BitOr( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE, HB_THREAD_INHERIT_MEMVARS ), {|| ExecQuery( cQuery, @aDadosCob, @cErro, aChave ) } )

WaitThread( nThread )

FUNCTION ExecQuery( cQuery, aDados, cErro aChave )
LOCAL oRecordSet

   Hb_Default(@aDados, {})
   Hb_Default(@cErro, "")
   Hb_Default(@aChave, {})
   
   IF oConexao:AdoSelect( @oRecordSet, @aDados, cQuery, aChave, , @cErro, , oClPF:ListaFuncoes() ) == 0
   ENDIF

RETURN aDados

FUNCTION WaitThread( nThread )

   DO WHILE .T.
      IF Hb_ThreadWait( nThread, 0.1, .T. ) == 1
         EXIT
      ENDIF
      hwg_DoEvents()
   ENDDO

RETURN Nil

StartThread()

10 Ago 2020 21:49

Faço filtro em mais de 1000000 de registros usando thread, demora cerca menos de 2 segundos, a tabela no MAriaDb tem indice que ajuda na consulta

StartThread()

10 Ago 2020 21:54

O resultado dessa consulta alimenta uma grid da hwgui com tamanho variável, que pode ter 1 linha ou mais de 1000 linhas

StartThread()

10 Ago 2020 21:56

Uso assim pra não ficar com aquela mensagem "Esta janela não está respondendo", muito feio

StartThread()

10 Ago 2020 23:33

Eu comecei usando temporário em DBF, e é muita perda de tempo mesmo.
A consulta ao SQL é 1 segundo, e pra gravar em DBF pode demorar vários minutos.

Usa do jeito que foi retornado, ou, se faz questão de deixar igual DBF, use SQLMIX.

Quanto à mensagem "esta janela não está respondendo", aí é quando o processo é demorado.
Se for 1 ou 2 segundos, dá pra conviver com a mensagem.
Postar uma resposta