Página 5 de 5

StartThread()

Enviado: 30 Out 2020 17:22
por vilian
Passando só para destacar que MultiThread no xHarbour não funciona. Se vc usa xHarbour, nem perca seu tempo tentando.

StartThread()

Enviado: 11 Nov 2020 08:14
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!

StartThread()

Enviado: 11 Nov 2020 21:08
por asimoes
Não perca tempo com xHarbour, você não vai encontrar solução aqui no site, muito raro

StartThread()

Enviado: 13 Jan 2021 22:03
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.

StartThread()

Enviado: 19 Jan 2021 10:53
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!

StartThread()

Enviado: 15 Jun 2024 10:52
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.