2010-04-14 4 views
3

Je Familiarisation avec C# jour par jour et je suis tombé sur ce morceau de codebesoin d'une explication sur ce code - C#

public static void CopyStreamToStream(
Stream source, Stream destination, 
Action<Stream,Stream,Exception> completed) { 
byte[] buffer = new byte[0x1000]; 
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null); 

Action<Exception> done = e => { 
    if (completed != null) asyncOp.Post(delegate { 
     completed(source, destination, e); }, null); 
}; 

AsyncCallback rc = null; 
rc = readResult => { 
    try { 
     int read = source.EndRead(readResult); 
     if (read > 0) { 
      destination.BeginWrite(buffer, 0, read, writeResult => { 
       try { 
        destination.EndWrite(writeResult); 
        source.BeginRead(
         buffer, 0, buffer.Length, rc, null); 
       } 
       catch (Exception exc) { done(exc); } 
      }, null); 
     } 
     else done(null); 
    } 
    catch (Exception exc) { done(exc); } 
}; 

source.BeginRead(buffer, 0, buffer.Length, rc, null); 

}

De cet article Article

Qu'est-ce que Je n'arrive pas à suivre est-ce que comment le délégué est-il averti que la copie est faite? Dire une fois la copie terminée, je veux effectuer une opération sur le fichier copié.

Et oui, je sais que cela peut me dépasser étant donné mes quelques années en C#.

Répondre

2

Le délégué est enveloppé dans un autre délégué, appelé done. Ceci est appelé dans les blocs catch, ainsi que dans le bloc else vers la fin du délégué AsyncCallback, qui à son tour est passé à BeginRead:

AsyncCallback rc = null; 
rc = readResult => { 
    try { 
     int read = source.EndRead(readResult); 
     if (read > 0) { 
      destination.BeginWrite(buffer, 0, read, writeResult => { 
       try { 
        destination.EndWrite(writeResult); 
        source.BeginRead(
         buffer, 0, buffer.Length, rc, null); 
       } 
       catch (Exception exc) { done(exc); } // <-- here 
      }, null); 
     } 
     else done(null); // <-- here 
    } 
    catch (Exception exc) { done(exc); } // <-- and here 
}; 
5

Le

done(exc); 

et

else done(null); 

bits exécuter le Action<Exception> qui à son tour appellera le Action<Stream, Stream, Exception> passé à l'aide de la completed paramètre.

Cela se fait à l'aide AsyncOperation.Post pour que le délégué completed est exécuté sur un fil approprié.

EDIT: utiliser cette fonctionnalité? Quelque chose comme ceci:

CopyStreamToStream(input, output, CopyCompleted); 
... 

private void CopyCompleted(Stream input, Stream output, Exception ex) 
{ 
    if (ex != null) 
    { 
     LogError(ex); 
    } 
    else 
    { 
     // Put code to notify the database that the copy has completed here 
    } 
} 

Ou vous pouvez utiliser une expression lambda ou méthode anonyme - cela dépend de la quantité de logique dont vous avez besoin.

+0

Jon: Si je disais que je voulais signaler à une base de données que la copie est terminée, comment est-ce que je définirais cela dans ce code? – ltech

+0

@ltech: Vous passeriez une action appropriée (qui notifiait la base de données) comme argument pour le paramètre 'completed'. –

+0

Jon: donc ce changement Action done = e => { if (terminé! = Null) asyncOp.Post (délégué { terminé (source, destination, e);}, null); }; à action done = e => { si asyncOp.Post (délégué { terminé (source, destination, e, DBWork());}, null) (terminée! = Null); }; – ltech

1

Les lignes done(...) représentent l'endroit où le délégué est déclenché. Le délégué est attribué plus tôt dans le code à savoir

Action<Exception> done = e => { 
    if (completed != null) asyncOp.Post(delegate { 
     completed(source, destination, e); }, null); 
}; 
0

@ltech - Puis-je utiliser pour copier plusieurs fichiers sur un serveur? Exemple: dans une boucle for Puis-je appeler cette méthode et serait-ce la même chose que d'instancier des threads ou d'appeler un délégué via un modèle de commande pour déplacer plusieurs fichiers?