2 votes

Sous Windows, comment forcer fread de C à retourner même s'il n'y a pas d'entrée en attente ?

Dans un programme Windows avec deux threads : thread1 y thread2 .

Quand thread1 est bloqué dans l'appel fread(buffer, 1, 10, stdin) en attendant les commentaires, est-il possible de faire quelque chose à partir de thread2 pour forcer fread pour revenir ?

Jusqu'à présent, j'ai essayé d'appeler fclose(stdin) de thread2 mais cela ne semble pas fonctionner. Le programme reste bloqué à l'étape fclose jusqu'à ce qu'une entrée soit disponible dans le champ stdin flux.

Ce que j'essaie de faire, c'est de terminer thread1 avec élégance au lieu de le tuer avec TerminateThread parce qu'il y a du travail que thread1 doit faire à la fin.

Un autre élément à prendre en compte est que stdin est une extrémité d'un tuyau nommé. Je n'ai pas le contrôle du programme à l'autre bout du tuyau.
Ce dont j'ai besoin, c'est de déconnecter mon programme de son extrémité du tuyau ( stdin dans ce cas).

5voto

R.. Points 93718

Appel à fclose(stdin) est une très mauvaise idée ; elle provoque un comportement indéfini si elle se produit avant que la fonction fread (par rapport auquel il n'est pas ordonné) ou si le thread qui appelle fread fait tout ce qui est sinon avec stdin après fread revient, et il ne débloque pas le fread desde fclose ne peut pas continuer tant qu'il n'a pas obtenu un verrou sur stdin que le projet en cours fread est exclu.

stdio est fondamentalement inadapté à ce que vous voulez faire ici. Vous pourriez le rafistoler en faisant suivre les données par un second tuyau, avec un autre thread lisant les données de stdin et l'écriture dans votre nouveau tuyau. Ensuite, vous pouvez interrompre un fread sur l'extrémité de lecture de votre tuyau en fermant l'extrémité d'écriture de celui-ci. Le fil supplémentaire sera toujours bloqué, mais cela n'a pas vraiment d'importance si vous êtes sur le point de terminer de toute façon. Alternativement (et c'est probablement plus propre), vous pouvez utiliser des descripteurs de fichiers (ou des handles de fichiers Windows) au lieu de stdio et de poll (ou l'équivalent Windows) pour déterminer s'il y a une entrée à lire. Vous pouvez combiner ces approches pour placer la logique de gestion des fichiers spécifique à Windows dans le thread supplémentaire (ce qui permet de le terminer proprement) et continuer à utiliser la fonction portable stdio dans le fil logique de votre programme.

2voto

HrW Points 136

Si vous ne pouvez pas utiliser CancelSynchronousIo vous pouvez fermer le gestionnaire de fichier sous-jacent avec CloseHandle comme ceci :

CloseHandle((HANDLE)_get_osfhandle(_fileno(stdin))) ;

Cela devrait causer fread pour revenir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X