2010-07-11 5 views
1

J'ai fait beaucoup de recherches et je n'arrive toujours pas à trouver comment résoudre mon problème. J'écris un programme d'interface graphique (dans WinAPI donc pas MFC s'il vous plaît) pour communiquer avec un autre programme (basé sur la ligne de commande). J'utilise des pipes anonymes puisque tout est local (mais peut-être que les pipes nommées seraient mieux?) Que j'utilise alors CreateProcess(); pour exécuter le programme, j'essaie d'obtenir la sortie de.Aide sur les E/S asynchrones

Maintenant, je viens de passer de synchrone à asynchrone il y a quelques heures et je rencontre quelques problèmes (même si synchrone n'a pas fait ce que je voulais de toute façon). Le premier problème est que je suis toujours confronté au même problème que j'avais lors de l'exécution des E/S synchrones; si je lance ma fonction "lire" (ou "écrire" d'ailleurs) plus d'une fois, le programme va se bloquer. Je ne peux pas avoir cela parce que le but du programme est de mettre à jour périodiquement à l'interface graphique ce que la sortie de l'invite de commande est.

Le deuxième problème, et finalement plus grave est un nouveau avec mon E/S asynchrone; il ne lit pas la sortie entière comme mon synchrone a fait. Il lit jusqu'à ce que le programme que je suis en train de lire envoie le caractère de retour (ou bien c'est simplement une coïncidence que c'est le moment où il arrête de lire). J'ai le sentiment que je ne comprends peut-être pas complètement les capacités de l'OVERLAP, mais je me sens embourbé en lisant tellement de MSDN en ce moment, alors peut-être que j'en oublie certains aspects importants.

Donc, fondamentalement, le code ci-dessous est le strict minimum de ce que je fais. J'ai essayé d'utiliser diverses techniques de boucles for() et while() pour essayer de passer en revue toutes les données de sortie, mais il semble que ce ne soit pas le cas. Notez que BUFSIZE est défini à 0x1000 qui est en fait plus que le petit programme de test que j'ai écrit pour cela même.

::ReadFile(_hChild_Out_Rd, chBuf, BUFSIZE, &dwRead, &o1); 
chBuf[dwRead] = '\0'; 
::SetDlgItemTextA(global,IDO_WORLDOUT,chBuf); 

Est-ce que quelqu'un a des idées?

Merci beaucoup pour votre aide!

Cordialement,
Dennis M.

Répondre

2

Cela ressemble à un code synchrone. Avec les E/S asynchrones (OVERLAPPED), vous ne pouvez pas utiliser le tampon tant que l'opération n'est pas terminée. Définissez le membre hEvent de la structure OVERLAPPED et modifiez votre boucle principale de PeekMessage à MsgWaitForMultipleObjects afin que votre programme puisse répondre aux événements d'E/S. Ensuite, vous pouvez attendre à la fois sur le handle d'opération OVERLAPPED et sur le handle de processus, afin de savoir quand l'autre programme s'est arrêté.

+0

Ma seule question maintenant est comment puis-je écrire le processus dans un tube nommé? J'ai créé un tube de nom et essayé d'exécuter un processus à travers celui-ci de la même manière qu'un tuyau anonyme, mais je ne peux pas accéder à la sortie. Des idées? – RageD

+0

Un pape anonyme devrait fonctionner correctement à cette fin, mais si vous voulez utiliser des canaux nommés, sachez que vous devez ouvrir les deux extrémités séparément (et les deux extrémités sont bidirectionnelles), contrairement au cas anonyme où vous avez une paire de poignées à l'une ou l'autre extrémité d'un canal unidirectionnel avec un seul appel d'API. –

+0

Est-ce que les handles de fichiers renvoyés par 'CreatePipe()' ont même un ensemble 'FILE_FLAG_OVERLAPPED'? 'CreatePipe()' n'a pas de paramètre "mode fichier" ou "mode ouvert". – bk1e

0

Vous pouvez regarder dans les fichiers mappés en mémoire, vous pouvez construire quelque chose dans la mémoire qui est une file d'attente et écrire à partir d'un endroit et lire de l'autre. Dans un projet, j'avais une file d'attente circulaire où un processus écrivait dans la file d'attente et l'autre lisant chaque fois qu'il avait le temps.

Vous créez un fichier de mémoire mappée comme ceci:

SECURITY_ATTRIBUTES sa; 
sa.bInheritHandle = TRUE; 
sa.nLength = sizeof(sa); 
sa.lpSecurityDescriptor = NULL; 

hdFile = CreateFileMapping(INVALID_HANDLE_VALUE,&sa, 
    PAGE_READWRITE,0,dwBufSize, L"SomeName"); 

Ensuite, vous obtenez un pointeur vers la mémoire partagée comme celui-ci

pOutSharedMemory=MapViewOfFile(hdFile,FILE_MAP_ALL_ACCESS,0,0,dwBufSize); 

maintenant, vous pouvez mapper des pointeurs à la mémoire

par exempledeux compteurs de garder une trace de l'endroit où vous êtes en mémoire (au sein dwBufSize)

pdwReadOffset = reinterpret_cast<DWORD*>(pOutSharedMemory) 
pdwWriteOffset = pdwReadOffset + sizeof(DWORD) 

alors une struct qui vous donne ensuite lecture/écriture à la mémoire en utilisant memmove

vous devez prendre soin de Synchronisation en place à l'aide de sections critiques, etc.

+0

Vous devez vraiment utiliser un canal, je ne connais aucun moyen de définir le membre 'hStdOutput' de' STARTUPINFO' sur une région mappée en mémoire, et le processus fils ne sait pas comment synchroniser l'accès au buffer circulaire . http://msdn.microsoft.com/en-us/library/ms686331(v=VS.85).aspx –

+0

en ayant différents compteurs d'écriture en lecture et ayant un mutex devrait être suffisant pour les synchroniser, mais je suis d'accord qu'un tuyau nommé peut-être le meilleur dans la situation OPs, présentant juste une alternative que j'ai utilisée il y a quelques années. –

Questions connexes