carlosmsi Posted June 6, 2019 Report Share Posted June 6, 2019 Quando tento acessar o comando EX: oSLFOOD:= oBanco:RowSet( "SELECT * FROM SLFOOD" , .t. ) no principal funciona, mas dentro da função da thread da erro como no exemplo, mais ou menos o que queria fazer. Function Main() cPastadoBanco := cLinguagem := cFilePath( ExeName() ) FWCONNECT oBanco HOST cPastadoBanco LANGFOLDER cLinguagem DATABASE "BASEMDB" IF oBanco == nil ? "Connect fail" ELSE aEstr:={} AADD( aEstr ,{"PED_ID" ,'varchar(60)', 60,0,"PRI" } ) IF !oBanco:TableExists( "SLFOOD" ) oBanco:CreateTable( "SLFOOD",aEstr ) ELSE //lChg := ChkStruct("slfood", aEstr, oBanco) ENDIF ENDIF //EXECUTAR THREAD FUNÇÃO AUTENTICACAO hb_threadStart( HB_THREAD_INHERIT_PUBLIC, HB_THREAD_INHERIT_PRIVATE, HB_THREAD_INHERIT_MEMVARS, { || AUTENTICACAO() } ) // FORA DA THREAD //AQUI FUNCIONA O COMANDO DE MARIADB NORMAL oSLFOOD:= oBanco:RowSet( "SELECT * FROM SLFOOD" , .t. ) RETURN .t. ***************************************************** FUNCTION AUTENTICACAO() //ENTRANDO NA FUNÇÃO POR THREAD //SE EU TENTAR USAR O COMANDO DE MARIADB AQUI DÁ ERRO oSLFOOD:= oBanco:RowSet( "SELECT * FROM SLFOOD WHERE PED_PED LIKE 'PLC%'" , .t. ) RETURN .T. Quote Link to comment Share on other sites More sharing options...
emotta Posted June 7, 2019 Report Share Posted June 7, 2019 Vamos la: Se for xHarobur o conceito de thread não é threadsafe, ou seja, as variaveis são compartilhadas. Não funciona legal e minhas experiencias com thread em xHarbour nunca foram boas, do nada a aplicação fecha, da conflitos, erros estranhos, etc... Então abandonei. Se for Harbour: Aí funciona legal, em Harbour é threadsafe, ou seja, funciona como se tivesse aberto outro executavel, fica tudo separado. É possivel criar variaveis que são "vistas" na thread principal e também nas outras, mas isso deve ser usado com cautela. Então agora vamos ao seu problema: Se vc estiver usando xHarbour aconselho vc a abandonar o uso de thread. Agora se estiver usando Harbour posta pelo menos o erro que está dando pra tentar ajudar, mas pelo que entendi o seu código vc quer fazer uma busca no banco de dados e enquanto a busca é feita a aplicação é liberada pra outras coisas, certo? Esse é o objetivo? Quote Link to comment Share on other sites More sharing options...
carlosmsi Posted June 8, 2019 Author Report Share Posted June 8, 2019 Esqueci de mencionar, então eu estou usado com harbour. O que estou tentando fazer é que no principal tenho um xbrowse, e na thread eu tenho uma função que ficar pegando informações de uma api e grava no banco mariadb e estou tentando retornar no xbrowse principal, só que se eu executo pra conectar com o mariadb no principal da erro dentro da thread, e se executo dentro da thread da erro no principal, e se executo pra conectar nos dois ele não grava no mariadb. Function Main() local oDlgiFood public clientid, clientsecret, nome, senha, token, cUrl, oListaPedidos, oSLFOOD public oBanco token:= 0 CRIARBANCO(@oBanco) clientid:= 'x' clientsecret:= 'x' nome:= 'POS' senha:= 'POS' hb_threadStart(HB_THREAD_INHERIT_PUBLIC,HB_THREAD_INHERIT_PRIVATE,HB_THREAD_INHERIT_MEMVARS, { || AUTENTICACAO(clientid,clientsecret,nome,senha,token,cUrl,@oListaPedidos,@oBanco,@oSLFOOD) } ) cSql:= "SELECT * FROM SLFOOD ORDER BY PED_PED" oSLFOOD:= oBanco:RowSet( cSql, .t. ) DEFINE FONT oFont NAME "MS Sans Serif" SIZE 0, -10 DEFINE DIALOG oDlgiFood RESOURCE "PRINCIPAL" FONT oFont REDEFINE XBROWSE oListaPedidos; DATASOURCE oSLFOOD ; STYLE FLAT; ID 4009 OF oDlgiFood UPDATE ADD COLUMN TO xbrowse oListaPedidos DATA oSLFOOD:PED_PED WIDTH 130 ALIGN LEFT ; HEADER "PEDIDO" ADD COLUMN TO xbrowse oListaPedidos DATA oSLFOOD:PED_COD WIDTH 100 ALIGN LEFT ; HEADER "ORDEM" //-- Estilo --------------------------------// oListaPedidos:nMarqueeStyle := MARQSTYLE_HIGHLROW oListaPedidos:nColDividerStyle := LINESTYLE_LIGHTGRAY oListaPedidos:nRowDividerStyle := LINESTYLE_LIGHTGRAY oListaPedidos:lAllowColSwapping := .F. //---> Trocar Colunas oListaPedidos:lAllowRowSizing := .F. //---> Nao move as Linhas oListaPedidos:lFooter := .F. //---> Rodapé oListaPedidos:lHScroll := .F. //---> Barra de rolagem horizontal oListaPedidos:bClrSel := {|| {CLR_WHITE,CLR_BLACK}} //---> Cor do selecionado sem clique oListaPedidos:bClrSelFocus := {|| {CLR_BLACK,CLR_AZULCLARO }} //---> Cor do selecionado oListaPedidos:nRowHeight := 20 //---> Tamanho da Linha dos campos ( PADRAO 16) oListaPedidos:nHeaderLines := 02 //---> Numeros de Linhas do Cabecalho. TAMANHO oListaPedidos:nDataLines := 2 //---> Numero de Linhas dos dados ACTIVATE DIALOG oDlgiFood CENTERED RETURN nil ********************************************************************************** FUNCTION AUTENTICACAO(clientid,clientsecret,nome,senha,token,cUrl,oListaPedidos,oBanco,oSLFOOD) //1-AUTENTICANDO //CRIARBANCO(@oBanco) cUrl:= 'https://oauth/token' //CRIAR EM JSON cXml:= [client_id=]+clientid+[&client_secret=]+clientsecret+[&grant_type=password&username=]+nome+[&password=]+senha oHttp:= CreateObject( 'MSXML2.ServerXMLHTTP' ) oHttp:Open( "POST" , cUrl, .F. ) oHttp:setRequestHeader("content-type", "application/x-www-form-urlencoded") oHttp:send(cXml) cc1:= oHttp:ResponseText //PEGAR RESPOSTA JSON aHasRes:= hash() hb_jsondecode(cc1 ,@aHasRes) //Parse JSON to hash token:= aHasRes["access_token"] POLLING(token,oBanco,oListaPedidos,oSLFOOD) RETURN .T. ********************************************************************************** FUNCTION POLLING(token,oBanco,oListaPedidos,oSLFOOD) cUrl:= 'https://events%3Apolling' qSeg:= 0 qSegundos:= 10000//VAL( SUBSTR( TIME(),7,2) ) DO WHILE qSeg <= qSegundos oHttp:= CreateObject( 'MSXML2.ServerXMLHTTP' ) oHttp:Open( "GET" , cUrl, .f. ) oHttp:setRequestHeader("content-type","application/json") oHttp:setRequestHeader("cache-control","no-cache") oHttp:setRequestHeader("accept","application/json") oHttp:setRequestHeader("Authorization","bearer "+token) oHttp:setRequestHeader("cache-control","no-cache") oHttp:setRequestHeader("accept","application/json") oHttp:send() cc1:= ALLTRIM(oHttp:ResponseText) IF oHttp:status = 404 // SEM PEDIDOS oBanco:Execute( "DELETE FROM SLFOOD" ) ELSEIF oHttp:status = 401 //- Unauthorized AUTENTICACAO() ELSEIF oHttp:status = 200 // COM SUCESSO MSGINFO("COM PEDIDO","OK") //MSGINFO(cc1,"OK") HB_MemoWrit('LISTA.TXT',cc1) // GRAVAR COMANDO EM LOG aJSON := {}//hb_hash() HB_JSONDecode(cc1, @aJSON) IF hb_isArray(aJSON) = .T. //deve ser true qtdPed:= Len(ajSon) FOR i=1 TO qtdPed IF aJSON[i]['code'] = "PLACED" oSLFOOD:= oBanco:RowSet( "SELECT * FROM SLFOOD WHERE PED_PED LIKE '"+aJSON[i]['correlationId']+"%'", .T. ) IF EMPTY(oSLFOOD:PED_PED) = .T. MSGINFO("NAO EXISTE ESSE PEDIDO","OK") cSql:= "SELECT * FROM SLFOOD ORDER BY PED_PED" oSLFOOD:= oBanco:RowSet( cSql, .t. ) oSLFOOD:GoBOTTOM() nPED_ID := aJSON[i]["id"] nPED_COD:= aJSON[i]['code'] nPED_PED:= aJSON[i]['correlationId'] NPED_DEH:= aJSON[i]['createdAt'] oBanco:Insert("SLFOOD", "PED_ID , PED_COD, PED_PED, PED_DEH", ; { nPED_ID ,nPED_COD,nPED_PED,nPED_DEH}) cReference:= aJSON[i]['correlationId'] ORDES(cReference,token) else MSGINFO("já existe esse pedido") nPED_ID := aJSON[i]["id"] nPED_COD:= aJSON[i]['code'] nPED_PED:= aJSON[i]['correlationId'] NPED_DEH:= aJSON[i]['createdAt'] oBanco:Replace("SLFOOD", "PED_ID , PED_COD, PED_PED, PED_DEH", ; { nPED_ID ,nPED_COD,nPED_PED,nPED_DEH}) ENDIF ENDIF NEXT ENDIF ENDIF cSql:= "SELECT * FROM SLFOOD ORDER BY PED_PED" oSLFOOD:= oBanco:RowSet( cSql, .t.) oListaPedidos:oDbf:= oSLFOOD oListaPedidos:Refresh(.T.) ENDDO RETURN .T. o erro que ocorre quando coloco pra executar só no principal ou só dentro da thread é Called from MYSQL_EXECUTE(0) in .\source\internal\FWMARIA.PRG Called from FWMARIACONNECTION:EXECUTE_SQL(5771) in .\source\internal\FWMARIA.PRG Called from FWMARIACONNECTION:EXECUTE(6025) in .\source\internal\FWMARIA.PRG Called from POLLING(197) in IFOOD.PRG Called from AUTENTICACAO(169) in IFOOD.PRG Called from (b)MAIN(44) in IFOOD.PRG Quote Link to comment Share on other sites More sharing options...
emotta Posted June 10, 2019 Report Share Posted June 10, 2019 Temos a Thread principal (aplicação normal) e as threads filhas (criados pelo Startthread) Os comandos que envolvem tela (obrw:refresh, msgstop, msginfo, etc) só podem ser executados na thread principal. Então o que vc precisa fazer é encontrar alguma maneira da thread filha passar as informações para a thread pai e pela thread pai vc dar todos os comandos que envolvem tela ok? No seu caso minha sugestão é alterar a estrutura do programa e deixar a thread filha apenas executando a API e obtendo o retorno. Pra gravar no banco de dados e atualizar a tela você faz tudo pela pai. Para se comunicar entre as thread veja alguns exemplos, tem um tipo de variavel q vc cria pra que ela seja visivel entre ambas (pai e filha) mas agora não estou me recordando. Nos SAMPLES vc vai encontrar facilmente isso. Mas como falei, thread é buxa, se tiver outra alternativa a usar sem ser por thread é sempre melhor, mesmo sendo em Harbour onde thread funciona bem e sem bugs. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.