Página 1 de 2

envio de email em 2.plano

Enviado: 25 Out 2020 19:52
por Abel
ola pessoal,
tenho uma rotina que envia varios emails, eu monto um array de emails e ela faz um loop e fica enviado...

Código: Selecionar todos


for x=1 to len(q_email)
     envia_email(q_email[x], rA_CORPOEMAIL)
     exibe_contagem(x)
next x

O problema é que enquanto envia os emails do array q_email com um contador de envio, o sistema fica parado ate que todos os emails sejam enviados.

Eu gostaria de fazer isso em segundo plano, exibindo o quadro de contagem em qualquer cantinho da tela, e liberando o usuário de fazer qualquer outra
coisa no sistema, ou seja, colocar o envio dos emails em segundo plano.

Trabalho do modo console ainda, harbour 3.1.

Se tiverem algum exemplo fácil para eu adaptar, ou alguma dica do caminho a seguir me ajudaria muito.

Desde ja Agradeço
ABEL

envio de email em 2.plano

Enviado: 25 Out 2020 22:20
por asimoes
Tipico para ser executado em uma Thread

envio de email em 2.plano

Enviado: 26 Out 2020 02:28
por Abel
asimoes, poderia postar algum exemplo, olhei no forum mas nao consegui usar nenhum exemplo.
precisava saber qual include tenho que compilar junto para usar thead

Desde ja agradeço,
ABEL

envio de email em 2.plano

Enviado: 26 Out 2020 09:00
por dbsh
Inclua a diretiva
-mt

EXEMPLO:
Não vai compilar, mas use como modelo se for util.

Código: Selecionar todos

METHOD AtivaMonitoramento() CLASS ProcessoPai
LOCAL nCount := 0

HB_MutexLock( ::ReadMutex )
HB_MutexLock( ::ErroMutex )

IF ::ReadMonitor
    IF !IsValidThRead( ::ReadThRead )
        ::ReadThRead := HB_ThReadStart( {|| AguardaDadosFRead( Self ) } )
    ENDIF
    IF !IsValidThRead( ::ReadThRead )
        ::ErroNumero += PROCESS_ERRO_START_THREAD
        Debug display "monitor erro ao carregar thread receber dados" + xStr(::ErroNumero), 11
        RETURN .F.
    ENDIF
ENDIF

IF ::ErroMonitor
    IF !IsValidThRead( ::ErroThRead )
        ::ErroThRead := HB_ThReadStart( {|| AguardaErroFRead( Self ) } )
    ENDIF
    IF !IsValidThRead( ::ErroThRead )
        ::ErroNumero += PROCESS_ERRO_START_THREAD
        Debug display "monitor erro ao carregar thread receber erro" + xStr(::ErroNumero), 11
        RETU .F.
    ENDIF
ENDIF

Debug display "monitor ThRead iniciado", 11

HB_MutexUnLock( ::ReadMutex )
HB_MutexUnLock( ::ErroMutex )

RETU .T.



envio de email em 2.plano

Enviado: 26 Out 2020 09:12
por Itamar M. Lins Jr.
Olá!
Não precisa exclusivamente de MT para rodar tarefas em segundo plano.

Código: Selecionar todos

#include "hbmemory.ch"

PROCEDURE Main()

   LOCAL nH1, nH2, nH3, nH4
   LOCAL n := 0
   LOCAL aSign := { "|", "/", "-", "\" }
   LOCAL nPrev := Seconds()

   CLS
   ? "   Time:        Memory used:                          Milliseconds elapsed"
   ?
   ? "Can you see it ??? :) Press any key or wait 30 seconds"
   ?
   ?
   @ 10, 2 SAY "Memory before TEST() call" + Str( Memory( HB_MEM_USED ) )
   TEST()
   @ 11, 2 SAY "Memory after TEST() and before collecting" + Str( Memory( HB_MEM_USED ) )
   hb_gcAll()
   @ 12, 2 SAY "Memory after collecting" + Str( Memory( HB_MEM_USED ) )
   nH1 := hb_idleAdd( {||                             hb_DispOutAt( 0,  1, Time() ) } )
   nH2 := hb_idleAdd( {|| TEST(),                     hb_DispOutAt( 0, 21, Memory( HB_MEM_USED ) ) } )
   nH3 := hb_idleAdd( {|| iif( n == 4, n := 1, n++ ), hb_DispOutAt( 0, 41, aSign[ n ] ) } )
   nH4 := hb_idleAdd( {||                             hb_DispOutAt( 0, 61, 1000 * ( Seconds() - nPrev ) ), nPrev := Seconds() } )

   ? ValType( nH1 ), nH1, ValType( nH2 ), nH2, ValType( nH3 ), nH3, ValType( nH4 ), nH4

   Inkey( 30 )
   IF ! Empty( nH3 )
      @ 14, 2 SAY "Delete task 3: " + hb_ValToStr( nH3 )
      hb_idleDel( nH3 )
   ENDIF
   IF ! Empty( nH2 )
      @ 15, 2 SAY "Delete task 2: " + hb_ValToStr( nH2 )
      hb_idleDel( nH2 )
   ENDIF
   IF ! Empty( nH1 )
      @ 16, 2 SAY "Delete task 1: " + hb_ValToStr( nH1 )
      hb_idleDel( nH1 )
   ENDIF
   IF ! Empty( nH4 )
      @ 17, 2 SAY "Delete task 4: " + hb_ValToStr( nH4 )
      hb_idleDel( nH4 )
   ENDIF

   @ 18, 2 SAY "Memory after idle states" + Str( Memory( HB_MEM_USED ) )
   hb_gcAll()
   @ 19, 2 SAY "Memory after collecting" + Str( Memory( HB_MEM_USED ) )

   RETURN

STATIC PROCEDURE TEST()

   LOCAL a, b, c
   LOCAL cb

   a := Array( 3 )
   b := Array( 3 )
   c := Array( 3 )
   a[ 1 ] := a
   a[ 2 ] := b
   a[ 3 ] := c
   b[ 1 ] := a
   b[ 2 ] := b
   b[ 3 ] := c
   c[ 1 ] := a
   c[ 2 ] := b
   c[ 3 ] := c

   cb := {| x | x := cb }
   Eval( cb )

   RETURN
HB_IDLEADD()
Adds the background task.
Syntax
HB_IDLEADD( <bAction> ) --> nHandle
Arguments
<bAction> is a codeblock that will be executed during idle states. There are no arguments passed to this codeblock during evaluation.
Returns
<nHandle> The handle (an integer value) that identifies the task. This handle can be used for deleting the task.

Description
HB_IDLEADD() adds a passed codeblock to the list of background tasks that will be evaluated during the idle states. There is no limit for the number of tasks.
Examples
nTask := hb_idleAdd( {|| SayTime() } )

Saudações,
Itamar M. Lins Jr.

envio de email em 2.plano

Enviado: 26 Out 2020 09:35
por asimoes
Tinha esquecido de HB_IDLEADD, também deve funcionar, só toma cuidado de deletar o idle após o término do envio de email

envio de email em 2.plano

Enviado: 26 Out 2020 09:49
por Itamar M. Lins Jr.
Olá!
só toma cuidado de deletar o idle após o término do envio de email
IF ! Empty( nH1 )
@ 16, 2 SAY "Delete task 1: " + hb_ValToStr( nH1 )
hb_idleDel( nH1 )
ENDIF

Olhar no exemplo que postei e se possível executar para ver funcionando.

Saudações,
Itamar M. Lins Jr.

envio de email em 2.plano

Enviado: 14 Mar 2022 12:17
por Abel
oi pessoal, estava fazendo um teste de uma rotina em segundo plano e aparentemente no comando send() a tarefa em segundo plano para de funcionar e só retorna quando o send() termina sua execucao.

a minha ideia é que a tarefa em segundo plano fique algo na tela simulando um processamento para não parecer que travou mesmo que a pesquisa demora 10segs
por exemplo.

Desde ja agradeço !
ABEL

Código: Selecionar todos


// MEU FONTE
NTURN=0
NTURN1=0
rN_T=ATIVA_2PLANO()
//
CONSULTA_REQUISICAO()
//
DESATIVA_2PLANO(rN_T)



FUNCTION CONSULTA_REQUISICAO()    
  Local oOle, aRet, 
  //
  @ 5, 1 + 1 SAY "A"
    
    TRY
       oOle:=win_OleCreateObject("MSXML2.XMLHTTP")  
    Catch
       oOle:=CreateObject("Microsoft.XMLHTTP")
    End
    //
    @ 5, 1 + 1 SAY "B"
    oOle:Open( 'POST', "https://ws.apicep.com/cep.json?code=06233-030" , .f. )  // ESSE É UM EXEMPLO DE REQUISICAO Q ESTOU USANDO NO TESTE 
    //
    @ 5, 1 + 1 SAY "C"
    
    oOle:setRequestHeader("Content-Type", "application/json" )
    //
    @ 5, 1 + 1 SAY "D"   // aqui a funçao que esta rodando em segundo plano para até o send() ser executado
    //
    TRY 
       oOle:Send( )      
       
    CATCH
       //
       ALERT2('VERMELHO','Problemas na Consulta ...')  
       //
       RETURN ""
    End   
    //
    @ 5, 1 + 1 SAY "E"
    aRet:=oOle:Responsetext
    Do While oOle:readyState <> 4
       millisec(500)
    ENDDO
    //
    @ 5, 1 + 1 SAY "F"
    ALERT(aRet)
    //
    
RETURN ""  




PROCEDURE ATIVA_2PLANO()
X := hb_idleAdd( {|| Progress( @nTurn1, 30, 35 ) } )
RETURN X

PROCEDURE DESATIVA_2PLANO(X)
hb_idleDel( X )
RETURN 


PROCEDURE Progress( nProgress, nDrow, nDcol )

   LOCAL rA_CHAR, nRow := Row(), nCol := Col()

   
   @ nDrow-1, nDcol-1 SAY "     " COLOR 'W/G+'
   @ nDrow  , nDcol-1 SAY " [ ] " COLOR 'W/G+'
   @ nDrow+1, nDcol-1 SAY "     " COLOR 'W/G+'
   
   @ nDrow-1, nDcol+4 SAY "                                 " COLOR 'G/W*'
   @ nDrow  , nDcol+4 SAY " Aguarde, fazendo a consulta ... " COLOR 'G/W*'
   @ nDrow+1, nDcol+4 SAY "                                 " COLOR 'G/W*'
   
   DO CASE
      CASE nProgress = 0
          @ nDrow, nDcol + 1 SAY "-" COLOR 'W+/G+'
      CASE nProgress = 1
          @ nDrow, nDcol + 1 SAY "\" COLOR 'W+/G+'
      CASE nProgress = 2
          @ nDrow, nDcol + 1 SAY "|" COLOR 'W+/G+'
      CASE nProgress = 3
          @ nDrow, nDcol + 1 SAY "/" COLOR 'W+/G+'
   ENDCASE
   nProgress++

   IF nProgress == 4
      nProgress := 0
   ENDIF
RETURN



envio de email em 2.plano

Enviado: 17 Mar 2022 17:19
por carlaoonline
Bom dia!


Quem sabe criar um segundo aplicativo que é chamado pelo principal apenas para essa função.....
Um segundo aplicativo pode ser compilado apenas com as bibliotecas que vai precisar pra ele ao inves de todos os que tem no principal, pode ser feito em MiniGui, HMG, C, etc...

Ex.:
HB_RUN ( "ENVIA.EXE" )
ou

RUN ENVIA.EXE



Ele pode rodar com uma tela bem menor que caiba apenas a mensagem, pode rodar minimizado ou até sem tela (em segundo plano apenas na memória)...

envio de email em 2.plano

Enviado: 19 Mar 2022 12:46
por Abel
Ola,
seria uma ideia realmente, mas nao queria um outro EXE,
meu sistema é modo console, poderia ate ser uma janelinha windows de mensagem,
mas nao consegui fazer, uma mensagem em janela tipo windows com algo em movimento
demonstrando que esta sendo processado alguma tarefa.

att
ABEL

envio de email em 2.plano

Enviado: 19 Mar 2022 14:31
por Itamar M. Lins Jr.
Olá!
Simples, coloque a rotina, msg aqui dentro:

Código: Selecionar todos

    Do While oOle:readyState <> 4 
Saudações,
Itamar M. Lins Jr.

envio de email em 2.plano

Enviado: 19 Mar 2022 14:35
por Itamar M. Lins Jr.
Olá!
Cadê de fato a rotina que demora ? pq esse exemplo nem pisca, é muito rápido pegar CEP.

Saudações,
Itamar M. Lins Jr.

envio de email em 2.plano

Enviado: 30 Mar 2022 10:42
por Abel
oi Itamar,

não posso publicar aqui o http que chama essa API que demora um pouco para retornar, pq é particular desse cliente e ele não me autoriza.
coloquei a do cep como um exemplo apenas.

essa API faz o seguinte:
- ela abre um site, preenche dois campos, clica em um botao pesquisar, pega o resultado da pesqusisa, e devolve uma matriz que recebo no harbour e processo o resultado. Acho que essa api foi feita em phyton. Pelo harbour nao consegui desenvolver essa solucao por completo.

o ideal é que eu tivesse uma solucao direto pelo harbour sem a necessidade de chamar essa API

vou tentar colocar a msg do readystate

Obrigado por enquanto

envio de email em 2.plano

Enviado: 30 Mar 2022 11:02
por Abel
ola pessoal,

segue o trecho em harbour que faz a requisicao

Código: Selecionar todos

    oOle:Open( 'POST', "http://....." , .f. )
    //
    oOle:SetRequestHeader('token', nToken )  
    oOle:setRequestHeader("Content-Type", "application/json; charset=UTF-8" )
    oOle:SetRequestHeader( "Connection",       "keep-alive" )
    rA_BODY='{ "cpf": "'+ALLTRIM(rA_CPF)+'"  , "data": "'+dtoc(rD_DTNASC)+'" }'
    //
    TRY
       oOle:Send( rA_BODY )     // é aqui que ocorre o travamento temporario as vezes e aparece na janela console "nao respondendo..."
                                            // e ate mesmo uma janelinha em 2.plano que fiz para de funcionar, pois o harbour esta esperando um retorno

       // oOle:WaitForResponse( 100000 )  // nao faz diferença por ou tirar isso
   CATCH
       ALERT2('VERMELHO','Problemas na Consulta ...')  
       RETURN "CANCELA CONSULTA"
    End   
    //
    aRet:=oOle:Responsetext
    Do While oOle:readyState <> 4     // itamar quando chega aqui eu ja tenho o retorno do SEND(), entao nao adiantou colocar msg aqui 
       millisec(500)
    ENDDO
    RETURN aRet


envio de email em 2.plano

Enviado: 30 Mar 2022 11:12
por Itamar M. Lins Jr.
Olá!
Parece que é falha do SITE que RECEBE e RESPONDE, e não do programa. Porquê nessa parte é o SO(win) que gerência. É a mesma coisa que mandar imprimir via windows e ficar demorando sem imprimir, não resta nada a fazer a não ser esperar mesmo.

Teria que monitorar na CHEGADA. Tipo: Sim recebi sua solicitação e Ok! Enviei a resposta solicitada!

Saudações,
Itamar M. Lins Jr.