StartThread()

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

vilian
Usuário Nível 1
Usuário Nível 1
Mensagens: 27
Registrado em: 29 Ago 2013 17:39
Localização: Belem/Pa

StartThread()

Mensagem por vilian »

Passando só para destacar que MultiThread no xHarbour não funciona. Se vc usa xHarbour, nem perca seu tempo tentando.
Avatar do usuário
juniorcamilo
Usuário Nível 3
Usuário Nível 3
Mensagens: 343
Registrado em: 10 Nov 2006 09:12
Localização: Pará

StartThread()

Mensagem por juniorcamilo »

ola amigos!
como não tem como o startThread() funcionar em xHarbour 1.2.3, fiz um recurso técnico! Fiz minha automação chamar minha própria automação passando parâmetro, ou seja, executou o sistema em segundo plano e faz oq eu pedir e não para a execução!
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

StartThread()

Mensagem por asimoes »

Não perca tempo com xHarbour, você não vai encontrar solução aqui no site, muito raro
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
betovsp
Usuário Nível 1
Usuário Nível 1
Mensagens: 4
Registrado em: 09 Set 2005 13:34

StartThread()

Mensagem por betovsp »

juniorcamilo escreveu:ola amigos!
como não tem como o startThread() funcionar em xHarbour 1.2.3, fiz um recurso técnico! Fiz minha automação chamar minha própria automação passando parâmetro, ou seja, executou o sistema em segundo plano e faz oq eu pedir e não para a execução!
Olá meu amigo, consegue me mostrar como fez?
Estou precisando disso também.
Abraços.

Beto
betovsp@hotmail.com
(16)9112-5798
FWH 9.08 @SAY Xharb 1.2.1
Ribeirão Preto/SP
Avatar do usuário
juniorcamilo
Usuário Nível 3
Usuário Nível 3
Mensagens: 343
Registrado em: 10 Nov 2006 09:12
Localização: Pará

StartThread()

Mensagem por juniorcamilo »

betovsp escreveu: Olá meu amigo, consegue me mostrar como fez?
Estou precisando disso também.

Código: Selecionar todos

procedure EXECUTEDOWNLOADTRAVA(net,mArq)
   if Valtype(net) == "L"
      if net == .t.
         net := "net online"
      else
         net := "net offline"
      endif
   endif
   if at(":",CLDADOS) == 0
      ccomando := '"'+CURDRIVE()+':'+CLDADOS+EXENAME()+'"'+" EXECUTE$DownloadTrava('"+tira(net," ")+"','"+mArq+"')"
      winexec(cComando,2)
 
   else
      MyRun('"'+CLDADOS+EXENAME()+'"'+" EXECUTE$DownloadTrava('"+net+"','"+mArq+"')")
   endif
return

Código: Selecionar todos

FUNCTION Main(Envio)

*********************

if at("EXECUTE$",Envio) # 0
   TRY
      Private Funcao := substr(Envio,at("$",Envio)+1)
      &Funcao.
   CATCH e
      bErro := .t.
      DefError(e,.f.)
   FINALLY
      seguranca()
   END
endif
*********************
simplificando.. caso queira mais detalhes ! estou a disposição!
Avatar do usuário
clodoaldomonteiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 821
Registrado em: 30 Dez 2006 13:17
Localização: Teresina-PI
Contato:

StartThread()

Mensagem por clodoaldomonteiro »

Esta semana estava testando Thread no xHarbou e tb não consegui muita coisa, então resolvi perguntar para o ChatGPT se teria como fazer a rotina em C e implementar nos fontes do xHarbour e ficou assim:

Código C, salvar num arquivo .c e anexar no seu projeto:

Código: Selecionar todos

#include <windows.h>
#include <wininet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Estrutura para passar dados para a thread
struct ThreadData {
    char* cUrl;
    PHB_ITEM pArray;
    int nIndex;
};

// Protótipo da função findTable
char* findTable(const char* response);

// Função para gravar mensagem no arquivo "arqResult.txt"
void writeToFile(const char* message, int nIndex) {
    FILE *fp;
    int retries = 10;  // Número de tentativas
    int delay = 100;   // Tempo de espera em milissegundos

    while (retries > 0) {
        fp = fopen("arqResult.txt", "a");
        if (fp) {
            // Remover quebras de linha do message antes de escrever no arquivo
            size_t len = strlen(message);
            char *cleanedMessage = (char *)malloc((len + 1) * sizeof(char));
            if (cleanedMessage) {
                size_t j = 0;
                size_t i;
                for (i = 0; i < len; i++) {
                    if (message[i] != '\n' && message[i] != '\r') {
                        cleanedMessage[j++] = message[i];
                    }
                }
                cleanedMessage[j] = '\0';

                // Escrever no arquivo com o índice e o valor em texto
                fprintf(fp, "Index: %d Value: %s\n", nIndex, cleanedMessage);

                // Liberar a memória alocada para cleanedMessage
                free(cleanedMessage);
            }
            fclose(fp);
            break; // Sai do loop se o arquivo foi aberto e escrito com sucesso
        } else {
            retries--;
            Sleep(delay); // Espera antes de tentar novamente
        }
    }

    if (retries == 0) {
        printf("Não foi possível abrir o arquivo arqResult.txt após várias tentativas.\n");
    }
}

// Função para encontrar a posição do primeiro <table> em uma string
char* findTable(const char* response) {
    const char* tableTag = "<table";
    char* tablePos = strstr(response, tableTag);
    return tablePos ? strdup(tablePos) : NULL;
}

// Função executada pela thread para realizar a requisição HTTP
DWORD WINAPI HttpRequestThread(LPVOID lpParam) {
    // Declarar todas as variáveis no início
    struct ThreadData* data = (struct ThreadData*)lpParam;
    char* cUrl = data->cUrl;
    PHB_ITEM pArray = data->pArray;
    int nIndex = data->nIndex;

    HINTERNET hSession;
    HINTERNET hConnect;
    char buffer[4096];
    DWORD bytesRead;
    DWORD totalBytes = 0;
    char* response = NULL;
    PHB_ITEM pResponse;
    char* tableContent = NULL;

    // Abrir uma sessão de internet
    hSession = InternetOpen("MyAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hSession) {
        hConnect = InternetOpenUrl(hSession, cUrl, NULL, 0, INTERNET_FLAG_RELOAD, 0);
        if (hConnect) {
            while (InternetReadFile(hConnect, buffer, sizeof(buffer), &bytesRead) && bytesRead != 0) {
                response = (char*)realloc(response, totalBytes + bytesRead + 1);
                memcpy(response + totalBytes, buffer, bytesRead);
                totalBytes += bytesRead;
            }

            if (response) {
                response[totalBytes] = '\0';

                // Encontrar o conteúdo do primeiro <table> na resposta
                tableContent = findTable(response);
                if (tableContent) {
                    pResponse = hb_itemPutCL(NULL, tableContent, strlen(tableContent));
                    hb_arraySet(pArray, nIndex, pResponse);
                    hb_itemRelease(pResponse);
                    // Escrever resposta no arquivo
                    writeToFile(tableContent, nIndex);
                    free(tableContent);
                } else {
                    // Caso não encontre <table>, escrever "URL nao processada"
                    char* message;
                    size_t msgLen = snprintf(NULL, 0, "01 URL nao processada: %s", cUrl) + 1;
                    message = (char*)malloc(msgLen);
                    snprintf(message, msgLen, "01 URL nao processada: %s", cUrl);
                    writeToFile(message, nIndex);
                    free(message);
                }

                free(response);
            } else {
                // Caso não tenha resposta, escrever "URL nao processada"
                char* message;
                size_t msgLen = snprintf(NULL, 0, "01 URL nao processada: %s", cUrl) + 1;
                message = (char*)malloc(msgLen);
                snprintf(message, msgLen, "01 URL nao processada: %s", cUrl);
                writeToFile(message, nIndex);
                free(message);
            }

            InternetCloseHandle(hConnect);
        } else {
            // Caso a conexão falhe, escrever "URL nao processada"
            char* message;
            size_t msgLen = snprintf(NULL, 0, "01 URL nao processada: %s", cUrl) + 1;
            message = (char*)malloc(msgLen);
            snprintf(message, msgLen, "01 URL nao processada: %s", cUrl);
            writeToFile(message, nIndex);
            free(message);
        }
        InternetCloseHandle(hSession);
    } else {
        // Caso a sessão falhe, escrever "URL nao processada"
        char* message;
        size_t msgLen = snprintf(NULL, 0, "01 URL nao processada: %s", cUrl) + 1;
        message = (char*)malloc(msgLen);
        snprintf(message, msgLen, "01 URL nao processada: %s", cUrl);
        writeToFile(message, nIndex);
        free(message);
    }

    free(data->cUrl);
    free(data);

    // Redefinindo tableContent para NULL após uso
    tableContent = NULL;

    return 0;
}
Rotinas para anexar ao seu PRG:

Código: Selecionar todos

EXTERNAL _StartThread, _WaitForSingleObject, _CloseHandle

FUNCTION Main()
    LOCAL aUrls := { ;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=03",;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=01",;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=04",;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=05",;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=06",;
      "https://www.tcepi.tc.br/fiscalizado/situacao-das-prestacoes-de-contas/?type=municipais&ug=1449&ano=2024&mes=02" ;
    }
    LOCAL aHandles := ARRAY(LEN(aUrls))
    LOCAL i

    // Iniciar as threads
    FOR i := 1 TO LEN(aUrls)
        aHandles[i] := _StartThread(aUrls[i])
    NEXT

    // Esperar que todas as threads terminem
    FOR i := 1 TO LEN(aHandles)
        _WaitForSingleObject(aHandles[i])
        _CloseHandle(aHandles[i])
    NEXT

    ? "Todas as threads terminaram."
    RETURN NIL

PROCEDURE _StartThread(cUrl)
    LOCAL hThread, nIndex
    nIndex := 0 // Indice de exemplo, ajuste conforme necessário
    hThread := hb_HbMkProc( cUrl, nIndex )
    RETURN hThread

PROCEDURE _WaitForSingleObject(hThread)
    LOCAL nResult
    nResult := hb_HbMkWaitSingleObject( hThread )
    RETURN nResult

PROCEDURE _CloseHandle(hThread)
    hb_HbMkCloseHandle( hThread )
    RETURN NIL

O objetivo da rotina é abrir as páginas ao mesmo tem, para ser mais rápido, já que do lado do servidor, pode demorar de 3,5 a 22 segundos, e depois de abrir as páginas, salva seu html para se possa processar as <table> nele encontradas.

Abraços.
At. Clodoaldo Monteiro
Linguagens: Clipper / Harbour
Área de Atuação: Sistemas de gestão para Prefeituras Municipais
Fones: (86)3223-0653, 98859-0236
www.simplesinformatica.com.br
Responder