2016-12-22 1 views
1

Essayer d'optimiser un certain code, je fini par avoir ce genre de structure:Traduire imbriqués fonctions anonymes foreach boucle

StaticMethod(propA,() => 
{ 
    StaticMethod(propB,() => 
    { 
     StaticMethod(propC,() => 
     { 
      // Write line in console here to say it's done. 
     }); 
    }); 
}); 

Et je pensais qu'il devrait peut-être un moyen de simplifier que dans une certaine foreach ou même un boucle simple for, quelque chose comme ceci:

foreach (var prop in props) // consider that `props` can be iterated over 
{ 
    // Here I don't know how to chain everything... 
} 

Est-ce tout faisable? Ai-je besoin de modifier StaticMethod pour y parvenir? La boucle n'est peut-être pas suffisante, mais en étendant l'exemple à 1000 fonctions imbriquées, j'aurais besoin d'une itération.

est ici le concept de StaticMethod:

static void StaticMethod(Prop prop, Action done) 
{ 
    // Some code here 
    someDispatcher.BeginInvoke(() => { 
     // More code here 
     done(); 
    }); 
} 
+1

Votre exemple semble un peu trop généralisé; nous ne pouvons même pas dire si vos méthodes statiques agissent sur 'IEnumerable' (qui est requis pour' foreach') – BradleyDotNET

+0

Vos exigences ne sont pas claires. Vous voulez seulement traiter le prochain accessoire si l'actuel est OK? Quel est le point d'utiliser les lambdas? Ils ne font rien dans ce cas sauf à rendre le code plus confus. – SledgeHammer

+0

@BradleyDotNET Trop large: Trop de réponses possibles, bien s'il vous plaît pointer 1 ou 2 afin que je puisse voir à quel point c'est vraiment. De bonnes réponses trop longtemps, Servy a répondu dans un format approprié et a même ajouté plus de détails que j'ai demandé. C'est assez bouleversant depuis 1. J'ai édité l'OP et 2. Aucune édition n'est suggérée directement ou dans les commentaires. Aussi, il est explicite que ma question peut être posée avec oui/non ... – Mat

Répondre

4

C'est en effet un problème qui est extrêmement difficile avec un modèle de rappel de asynchronisme. Si vous transformez StaticMethod en un modèle d'asynchronisme basé sur Task, alors la solution devient beaucoup plus simple que. Si StaticMethod est votre propre méthode, idéalement, il suffit de la réécrire en utilisant un modèle Task entièrement, où il renvoie un Task quand il a fini, plutôt que de prendre un rappel, mais si ce n'est pas votre méthode, et vous pouvez ' Pour le changer, vous pouvez créer un wrapper utilisant un modèle basé sur Task. Pour transformer une méthode basée sur le rappel dans une Task méthode basée vous utilisez simplement un TaskCompletionSource:

public static Task StaticMethodAsync(object a) 
{ 
    var tcs = new TaskCompletionSource<bool>(); 
    StaticMethod(a,() => tcs.SetResult(true)); 
    return tcs.Task; 
} 

Maintenant que nous avons que nous pouvons écrire une méthode async qui itère sur props et appelle chaque méthode asynchrone à son tour:

foreach (var prop in props) 
{ 
    await StaticMethodAsync(prop); 
} 
// Write line in console here to say it's done. 

Si vous voulez vraiment pour résoudre ce problème tout en maintenant un modèle de rappel, vous pouvez , mais, comme vous pouvez le voir ci-dessous, il est beaucoup plus difficile à lire, comprendre et pas à pas:

public static void Foo(object[] props, Action callback) 
{ 
    int i = -1; 
    Action innerCallback = null; 
    innerCallback =() => 
    { 
     i++; 
     if (i < props.Length) 
     { 
      StaticMethod(props[i], innerCallback); 
     } 
     else 
     { 
      callback(); 
     } 
    }; 
    innerCallback(); 
} 
+2

Je ne vois pas de traitement asynchrone dans la question ...Pour moi, il ressemble à un modèle de constructeur maladroit ... Mais vous pourriez avoir raison. –

+0

@AlexeiLevenkov Le délégué ne renvoie rien, c'est donc une 'Action'. Si elle l'utilisait pour calculer une valeur, alors bien sûr. Mais puisqu'il s'agit d'une action, cette transformation serait valide, même s'il arrive à appeler le délégué avant son retour. Et le commentaire '// Ecrire une ligne dans la console ici pour dire que c'est fait. 'Fait un cas assez convaincant pour le délégué étant un rappel qui indique l'achèvement d'un processus. – Servy

+0

@Servy À première vue, cela semble prometteur. S'il vous plaît voir mon édition car je pense que j'aurais dû inclure ce code quand j'ai posté. Je vais essayer d'implémenter votre solution avec 'Task'! – Mat