Ir ao conteúdo
  • Cadastre-se

C Windows API - função Sleep() congela o aplicativo


Lucca Rodrigues
Ir à solução Resolvido por arfneto,

Posts recomendados

Boa tarde.

Alguém saberia um método de fazer quaisquer coisas que sejam, mas intercaladas por um intervalo de tempo?

Eu estava tentando carregar .bmp's intercalados por um intervalo de tempo num programinha usando a API do Windows, e obviamente a tela congela com a função Sleep() se eu tentar fazer qualquer coisa, como por exemplo, fechar a janela. Tentei fazer uma função com a WaitForSingleObject() para aguardar alguma tecla, e se recebesse, a função retornava, mas congela mesmo assim.

Qual seria o meio tradicional de fazer isso? Se é que há... Espero que não seja muito complicado (pois sou iniciante, só estou fazendo isso para brincar um pouco) :D

Eu tinha lido em algum lugar que eu teria que usar timers, estou um pouco confuso quanto à que fazer.

 

Obrigado desde já por qualquer ajuda.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Você tem que usar Threads. 

DWORD WINAPI tickThreadProc(HANDLE handle)
{
    for (;; ) {

       //Bote aqui o código para carregar o bitmap ou algo assim
        Sleep(200);
        
    }
    
}

Dessa forma seu programa não ficara travada, pois o carregamento é o Sleep estarão rodando em paralelo

Mais detalhes de como criar uma thread:

https://docs.microsoft.com/en-us/windows/win32/procthread/creating-threads

  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

@Flávio Pedroza Pra que aquele laço for lá?

Eu tinha feito o seguinte:

void intro (HWND hwnd){
    HWND inin4, inin3, inin2; // Janelas para os .bmp's

    sndPlaySound("auds\\intro.wav", SND_ASYNC); // Dura 21 seg.

    // Imagem 1
    Loadhbit("telas\\inicio4.bmp");
    inin4 = CreateWindowW(L"Static", L"",
        WS_CHILD | WS_VISIBLE | SS_BITMAP,
        0, 0, 640, 602, hwnd, (HMENU) ID_IMAGE10, NULL, NULL);

    SendMessage(inin4, STM_SETIMAGE,
        (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap);

    Sleep(7000);
    // Destrói imagem 1
    DestroyWindow(inin4);
	
    // Imagem 2
    Loadhbit("telas\\inicio3.bmp");
    inin3 = CreateWindowW(L"Static", L"",
        WS_CHILD | WS_VISIBLE | SS_BITMAP,
        0, 0, 640, 602, hwnd, (HMENU) ID_IMAGE11, NULL, NULL);

    SendMessage(inin3, STM_SETIMAGE,
        (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap);

    Sleep(7000);
    // Destrói imagem 2
    DestroyWindow(inin3);
	
    // Imagem 3
    Loadhbit("telas\\inicio2.bmp");
    inin2 = CreateWindowW(L"Static", L"",
        WS_CHILD | WS_VISIBLE | SS_BITMAP,
        0, 0, 640, 602, hwnd, (HMENU) ID_IMAGE12, NULL, NULL);

    SendMessage(inin2, STM_SETIMAGE,
        (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap);

    Sleep(7000);
    // Destrói imagem 3
    DestroyWindow(inin2);

    return;
}

E isso roda toda vez que a mensagem WM_PAINT é enviada.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

2 horas atrás, Lucca Rodrigues disse:

Tentei fazer uma função com a WaitForSingleObject() para aguardar alguma tecla, e se recebesse, a função retornava, mas congela mesmo assim

 

:) uma chamada a Wait() fez o programa esperar? Faz sentido. Se o seu programa só tem um processo executando é o que se espera afinal. Há muitas dessas funções e muitos objetos pelos quais pode esperar. E tem coisas como 
 

DWORD WaitForMultipleObjects(
  DWORD        nCount,
  const HANDLE *lpHandles,
  BOOL         bWaitAll,
  DWORD        dwMilliseconds
);

 

:D Sem mais trocadilhos, você pode em um processo esperar por várias coisas, mas também pode ter vários processos esperando pela mesma coisa. Ou esperando por uma entre várias coisas.  Mas enquanto você está esperando não quer dizer que esteja "congelado":  esse é o propósito. Está usando uma função que faz o contrário do que você precisa. Você quer continuar. 

 

Precisa fazer isso em C? Em C++ é mais fácil. Em especial em C++ '20.

 

Te mostrei uma vez um uso disso para um menu genérico que não usa leitura, e acho que pode usar aquilo para entender a diferença: você espera até acontecer algo: uma interrupção do sistema, algo digitado, a passagem de alguns ms, algum evento.

 

Em 2019 eu postei aqui um programa que fazia algo assim. Não tenho a referência aqui. Era um programa para leitura de processos.

 

Eis algo daquele programa

a ideia é usar um troço chamado TimerQueue

 

Isso cria uma fila e cada evento tem uma função associada, estilo javascript, uma função de callback. Quando o evento é sinalizado a função é disparada em outro thread.

 

    HANDLE  hTimer = NULL;
    if (!CreateTimerQueueTimer
    (
        &hTimer, *hTimerQueue,
        (WAITORTIMERCALLBACK)alarme,
        NULL, intervalo, 0, 0)
        )
    {
        printf("CreateTimerQueueTimer() falhou (%d)\n", GetLastError());
        return -2;
    };  // if
    if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
    {
        printf("WaitForSingleObject() falhou (%d)\n", GetLastError());
        CloseHandle(gDoneEvent);
        DeleteTimerQueue(hTimerQueue);
        return -3;
    };  // if
    CloseHandle(gDoneEvent);
    return 0;
};

 

E alarme() seria declarada assim
 

VOID CALLBACK   alarme(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
    SetEvent(gDoneEvent);
    return;
};

 

E o evento criado assim
 

    gDoneEvent = CreateEvent(NULL, 1, 0, NULL);
    if (NULL == gDoneEvent)
    {
        printf("CreateEvent() falhou (%d)\n", GetLastError());
        return -1;
    }
    *hTimerQueue = CreateTimerQueue();
    if (NULL == *hTimerQueue)
    {
        printf("CreateTimerQueue() falhou (%d)\n", GetLastError());
        return -2;
    }

 

Então acho que pode usar uma fila dessas e criar os timers com uma estrutura assim.

Deve ser mais simples que criar Threads um a um...

 

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@arfneto

2 minutos atrás, arfneto disse:

uma chamada a Wait() fez o programa esperar? Faz sentido.

Então, eu tinha feito uma função x que usa essa WaitForSingleObject() esperando por certas coisas da stdin, e o argumento que eu passo pra função x é o intervalo de tempo em milissegundos, igual a Sleep(). Caso a Wait() retorne WAIT_TIMEOUT, então ela esperou o que tinha que esperar (função x retorna 0), caso contrário, função x retorna o tempo restante em milissegundos.

Achei que assim eu poderia analisar o retorno da função x e, caso fosse maior que 0, ignorava todas as outras chamadas da mesma. Consegui mas não consegui, falha minha 🤪

 

14 minutos atrás, arfneto disse:

Precisa fazer isso em C? Em C++ é mais fácil. Em especial em C++ '20.

Eu não "preciso" fazer, só queria saber como se faz :D

Estou mais familiarizado com a linguagem C mesmo.

Por enquanto eu achei 1 exemplo de "animação" que usa threads como @Flávio Pedroza disse, mas não avistei algum com .bmp's. To tentando entender melhor como funciona isso, e acho que um exemplo é o melhor jeito.

46 minutos atrás, arfneto disse:

Então acho que pode usar uma fila dessas e criar os timers com uma estrutura assim.

Deve ser mais simples que criar Threads um a um...

Certo, vou dar uma pesquisada sobre isso.

Obrigado.

Link para o comentário
Compartilhar em outros sites

21 minutos atrás, Lucca Rodrigues disse:

Certo, vou dar uma pesquisada sobre isso

 

procure o programa que eu postei em '19. Pode ajudar.

Entendeu o que te mostrei? Você cria aquela fila (TimerQueue) e coloca nela chamadas sucessivas às funções que vão mostrar as suas imagens. Seu programa continua rodando e conforme os sinais chegam --- eventos --- suas funções vão rodando e mostrando os bitmaps. 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

  • Solução
4 horas atrás, Lucca Rodrigues disse:

Eu tinha feito o seguinte

 

... Sugiro muito que esqueça esse modo de programar. Ninguém usa isso desde o final dos '80 e deve ter uma boa razão. 

Não via aprender nada exceto sobre o message loop do Windows, e vai gastar um tempo enorme para um resultado em geral não tão bom. 

Use .Net e outra linguagem, ou Allegro5, ou SDL2 ou Qt5 ou GTK+ ou wswidgets para usar esses controles. É muito simples, tudo pareido e o resultado é bom e portável.

 

Se quer mesmo aprender algo básico e poderoso e complicado, mas útil depois de 1986 ;) , tente OpenGL ou DirectX.

 

Li agora melhor o que você quer fazer e pra isso não precisa de multithreading. Basta usar um slideshow e criar um timeframe. A menos que precise de fato processar algo durante a exibição

Pode usar o comum: uma taxa de atualização e a cada digamos .5s verifica uma fila de eventos, o seu "message loop". Assim pode inserir outras atividades, como um menu. E executa o que estiver na fila. Nada original :) 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@arfneto

42 minutos atrás, arfneto disse:

... Sugiro muito que esqueça esse modo de programar. Ninguém usa isso desde o final dos '80 e deve ter uma boa razão. 

Não via aprender nada exceto sobre o message loop do Windows, e vai gastar um tempo enorme para um resultado em geral não tão bom.

Se for algo simples, talvez nem gaste tanto tempo, e normalmente não uso isso, só estou tentando fazer uma espécie de "intro" pra um joguinho (é só um teste, não usa muitos recursos).

Daí o que resta saber fazer é isso mesmo. Qualquer dúvida que eu tiver, eu posto aqui novamente, mas antes vou dar uma pesquisada e tentar fazer o que disse :)

Link para o comentário
Compartilhar em outros sites

@arfneto @Flávio Pedroza Agradeço a ambos pela ajuda!

Eu até tinha conseguido fazer uma "animação" com .bmp's criando Threads com base no exemplo que eu havia mencionado (referência), mas não entendi muito bem como funciona, talvez eu teria que ler com mais calma o que a documentação diz.

Enquanto estava tentando fazer o que Arf disse, achei uma referência que trata de timers, e aparentemente é bem simples. Caso alguém venha a ter a mesma dúvida que eu, nesse link tem uma explicação e alguns exemplos.

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...