J'ai essayé de résoudre cet exercice d'examen "Programmation concurrente" (en C#) :
Sachant que
Stream
la classe contientint Read(byte[] buffer, int offset, int size)
yvoid Write(byte[] buffer, int offset, int size)
implémenter en C# les méthodesNetToFile
qui copie toutes les données reçues deNetworkStream net
à l'instanceFileStream file
instance. Pour effectuer le transfert, utilisez des lectures asynchrones et des écritures synchrones, en évitant qu'un thread soit bloqué pendant les opérations de lecture. Le transfert se termine lorsque lenet
L'opération de lecture renvoie la valeur 0. Pour simplifier, il n'est pas nécessaire de prendre en charge l'annulation contrôlée de l'opération.
void NetToFile(NetworkStream net, FileStream file);
J'ai essayé de résoudre cet exercice, mais j'ai du mal à répondre à une question liée à la question elle-même. Mais d'abord, voici mon code :
public static void NetToFile(NetworkStream net, FileStream file) {
byte[] buffer = new byte[4096]; // buffer with 4 kB dimension
int offset = 0; // read/write offset
int nBytesRead = 0; // number of bytes read on each cycle
IAsyncResult ar;
do {
// read partial content of net (asynchronously)
ar = net.BeginRead(buffer,offset,buffer.Length,null,null);
// wait until read is completed
ar.AsyncWaitHandle.WaitOne();
// get number of bytes read on each cycle
nBytesRead = net.EndRead(ar);
// write partial content to file (synchronously)
fs.Write(buffer,offset,nBytesRead);
// update offset
offset += nBytesRead;
}
while( nBytesRead > 0);
}
La question que je me pose est que, dans l'énoncé de la question, il est dit :
Pour effectuer le transfert, utilisez la méthode asynchrone. lectures asynchrones et des écritures synchrones, en évitant qu'un thread soit bloqué pendant les opérations
Je ne suis pas vraiment sûr que ma solution accomplisse ce qui est recherché dans cet exercice, parce que j'utilise AsyncWaitHandle.WaitOne()
pour attendre que la lecture asynchrone soit terminée.
D'un autre côté, je ne comprends pas vraiment ce que l'on entend par solution "non bloquante" dans ce scénario, étant donné que la fonction FileStream
write est censé être fait de manière synchrone... et pour cela, je dois attendre que NetworkStream
la lecture est terminée pour procéder à la FileStream
l'écriture, n'est-ce pas ?
Pouvez-vous, s'il vous plaît, m'aider avec ça ? Merci d'avance pour votre collaboration.
[EDIT 1] Utilisation de rappel solution
Ok, si j'ai compris ce que Mitchel Sellers y willvv J'ai reçu une réponse (merci les gars), on m'a conseillé d'utiliser une méthode de rappel pour transformer cela en une solution "non bloquante". Voici donc mon code...
byte[] buffer; // buffer
public static void NetToFile(NetworkStream net, FileStream file) {
// buffer with same dimension as file stream data
buffer = new byte[file.Length];
//start asynchronous read
net.BeginRead(buffer,0,buffer.Length,OnEndRead,net);
}
//asynchronous callback
static void OnEndRead(IAsyncResult ar) {
//NetworkStream retrieve
NetworkStream net = (NetworkStream) ar.IAsyncState;
//get number of bytes read
int nBytesRead = net.EndRead(ar);
//write content to file
//... and now, how do I write to FileStream instance without
//having its reference??
//fs.Write(buffer,0,nBytesRead);
}
Comme vous l'avez peut-être remarqué, je suis bloqué au niveau de la méthode de rappel, car je n'ai pas de référence à l'objet de l'appel. FileStream
où je veux invoquer la méthode "Write(...)".
En outre, il ne s'agit pas d'une solution sûre du point de vue des threads, car la fonction byte[]
est exposé et peut être partagé entre des utilisateurs concurrents NetToFile
invocations. Je ne sais pas comment résoudre ce problème sans exposer cette byte[]
dans l'outer-scope... et je suis presque sûr qu'il ne peut pas être exposé de cette façon.
Je ne veux pas utiliser une solution de méthode lambda ou anonyme, car cela ne fait pas partie du programme du cours de "programmation simultanée".