Jump to content
Fivewin Brasil

Thread com Mariadb


carlosmsi

Recommended Posts

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.

 

Link to comment
Share on other sites

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?

 

 

 

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...