Bonjour,
J'ai une application écrite en C Win32 API, qui effectue une boucle de traitement assez longue en arrière plan, qui met a jour une barre de progression, et qui éventuellement doit répondre a l'action d'un bouton d'annulation.
Le problème c'est que cela bloque la fenêtre principale et cause des problèmes de rafraichissement graphique.
La seule solution que j'ai trouvé c'est de créer un Thread pour cette boucle, et mettre un WM_TIMER qui regarde de manière périodique si le Thread est terminé pour ensuite redonner la main a certaine fonctions dans la fenêtre.
Est-ce la bonne solution ?
Y a t'il une autre façon de faire qui soit mieux prévue pour ça ?
Je n'ai pas réussi a trouver ce cas la sur Internet pour une solution "officielle", pourtant j'imagine que c'est un cas qui est souvent rencontré.
Merci d'avance pour votre aide.
Voila ma solution pour le moment:
BOOL Thread_Finished;
HANDLE hThread;
HWND DialogHwnd;
void Thread_Start(LPTHREAD_START_ROUTINE function)
{
EnableWindow(DialogHwnd, FALSE);
Thread_Finished = FALSE;
hThread = CreateThread(NULL, 0, function, NULL, 0, NULL);
}
void Thread_End(void)
{
if (hThread && Thread_Finished)
{
CloseHandle(hThread);
hThread = NULL;
EnableWindow(DialogHwnd, TRUE);
}
}
DWORD WINAPI Thread_Read(LPVOID lpParam)
{
int progress;
while (Traitement(&progress))
SendMessage(GetDlgItem(DialogHwnd, IDC_PROGRESSBAR), PBM_SETPOS, progress, 0)
Thread_Finished = TRUE;
return (0);
}
BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
DialogHwnd = hwnd;
hThread = NULL;
SetTimer(hwnd, 0, 500, (TIMERPROC)NULL);
return TRUE;
case WM_TIMER:
Thread_End(); // Periodically check if a Launched Thread Ended
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BTN_READ:
Thread_Start(Thread_Read);
return TRUE;
}
return FALSE;
}
return FALSE;
}
Zeph Le 11/05/2019 à 13:53 Pourquoi ne pas conserver ton thread, mais retirer le timer et utiliser à la place SendMessage à la fin de ton traitement pour envoyer un signal qui permettrait au thread de la fenêtre principale de savoir que l'opération est terminée ?

All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez
par ici :)
Merci pour les infos, je vais regarder ça.
Donc en tout cas, la bonne méthode est bien d'utiliser un thread, pour avoir une partie gestion de la fenêtre et une partie threadé avec gestion du traitement ?
Question, comment la partie UI donne l’info d’annulation à la boucle de traitement des données ? C’est à elle de checker régulièrement une variable, ou le thread se fait killer ?
Finalement j'ai utilisé SendNotifyMessageA (qui n'est pas bloquant), avec un paramètre WM_USER a la fin de mon thread, et je traite ce message dans ma fenêtre pour réactiver les boutons nécessaires.
C'est vrai que, je me souviens avoir tenter de "Threader" un vieux projet de Raytracer afin de pouvoir calculer plus vite, et en fait j'ai tout casser mon code qui ne fonctionne plus du tout, parceque il a fallu dupliquer des structures de données pour que chaque thread y accède séparément, et ça a pas mal compliquer la chose.
J'imagine que ce n'est pas tellement le fait que ça soit une variable globale qui pose problème, puisque même si je passe l'adresse d'une structure globale en paramètre de la fonction thread, ça ne changera rien, c'est plutôt l'accès concurrentiel aux données qui pose soucis ?
Il faut vraiment que je me penche sur ça pour étudier ce problème.
À bas niveau oui, mais en pratique pas besoin de réinventer la roue sur les OS modernes, autant utiliser directement des solutions de plus haut niveau (qui utilisent des mutexes en interne, ou des algos lock-free implémentés soigneusement).

—
Zeroblog —
« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » —
Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » —
GT TurboOui il y a ça, mais aussi plusieurs mécanismes de FIFO (par exemple les pipes) qui sont encore plus simples à utiliser pour implémenter le modèle producteur / consommateur.

—
Zeroblog —
« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » —
Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » —
GT Turbo