Comment le taux de retour à l'intérieur des méthodes anonymes?
Fondamentalement, je n'ai anonyme méthode que j'utilise pour mes BackgroundWorker
:
worker.DoWork += ( sender, e ) =>
{
foreach ( var effect in GlobalGraph.Effects )
{
//Returns EffectResult
yield return image.Apply (effect);
}
};
Quand je fais cela, le compilateur me dit:
"Le rendement de la déclaration ne peut pas être utilisé
à l'intérieur d'une méthode anonyme ou lambda
l'expression"
Donc dans ce cas, quelle est la façon la plus élégante pour ce faire? Btw, ce DoWork méthode est à l'intérieur d'une méthode statique, dans le cas où les questions de la solution.
- C'est le fond de travailleur de la production de la
image
ou est-ce le remplissage de laGlobalGraph.Effects
énumérable? - Oui, le BW est la production de l'image, mais les EffectResult a le statut de sujet de l'effet, et non des données d'image ou quelque chose comme ça.
- double possible de En C#, pourquoi pas une méthode anonyme contenir une instruction rendement?
Vous devez vous connecter pour publier un commentaire.
Malheureusement, vous ne pouvez pas.
Le compilateur ne vous permet pas de combiner les deux "magie" des morceaux de code. Les deux impliquent la réécriture de votre code à l'appui de ce que vous voulez faire:
Vous pouvez, cependant, réécrire le code de retour de la collection, donc dans votre cas particulier, je voudrais faire cela:
mais il semble bizarre pour un événement
(sender, e)
de retourner quoi que ce soit. Êtes-vous sûr que vous faites preuve d'un réel scénario pour nous?Modifier Ok, je pense je vois ce que vous essayez de faire ici.
Vous avez une méthode statique d'appel, et que vous voulez exécuter du code en arrière-plan, puis de renvoyer les données à partir de cette méthode statique une fois le fond appel se termine.
C'est, si elle est possible, n'est pas une bonne solution puisque vous êtes effectivement la pause d'un thread attente d'un autre, qui a commencé juste avant vous avez interrompu le fil. En d'autres termes, tout ce que vous avez à faire est d'ajouter les frais généraux de la commutation de contexte.
Au lieu de cela, vous devez juste le coup d'envoi du travail de fond, puis lorsque ce travail est terminé, le traitement des données qui en résultent.
return
à l'intérieur d'un lambda, qui vise à revenir à partir de l'affichage de la méthode. Unreturn
dans un lambda de retour de l'lambda lui-même.Peut-être juste de retour de l'expression linq et de reporter l'exécution comme rendement:
Sauf si je suis en manque de quelque chose, vous ne pouvez pas faire ce que vous demandez.
(J'ai une réponse pour vous, lisez donc passé mon explication de pourquoi vous ne pouvez pas faire ce que vous faites en premier, et alors lisez la suite.)
Vous complète de la méthode devrait ressembler à quelque chose comme ceci:
Si nous supposons que votre code est "légal" puis, quand
GetSomeValues
est appelé, même si leDoWork
gestionnaire est ajouté àworker
, l'expression lambda n'est pas exécutée jusqu'à ce que leDoWork
événement est déclenché. Donc, l'appel àGetSomeValues
complète sans retour à tous les résultats et les lamdba peut ou peut ne pas être appelé à un stade ultérieur - qui est alors trop tard pour l'appelant de laGetSomeValues
méthode de toute façon.Votre meilleure réponse est l'utilisation Rx.
Rx tourne
IEnumerable<T>
sur sa tête. Au lieu de demander les valeurs d'une énumération, Rx a des valeurs poussé à vous de uneIObservable<T>
.Car vous utilisez un arrière-plan travailleur et de réagir à un événement, vous êtes effectivement en ayant les valeurs poussé à vous déjà. Avec Rx, il devient facile de faire ce que vous essayez de faire.
Vous avez quelques options. Probablement le plus simple est de le faire:
Maintenant appelants de votre
GetSomeValues
méthode pourrait faire ceci:Si vous savez que
DoWork
est seulement à feu une fois, cette approche pourrait être un peu mieux:Ce code est un peu plus compliqué, mais il permet juste d'un unique effectuer des travaux de l'événement dans un flux de
EffectResult
objets.Puis le code d'appel qui ressemble à ceci:
Rx peut même être utilisé pour remplacer l'arrière-plan travailleur. Ce pourrait être la meilleure option pour vous:
Le code d'appel est la même que dans l'exemple précédent. Le
Scheduler.ThreadPool
dit Rx comment faire pour "planifier", le traitement des abonnements à l'observateur.J'espère que cette aide.
IEnumerable<EffectResult>
qui il a bloquer sur tout le BW est en train de faire sa chose. Vous pourriez ainsi éviter l'BW entièrement à cause de cela. Vous avez besoin d'utiliser quelque chose comme Rx ou le TPL.IEnumerable<EffectResult>
.IEnumerable<T>
est un appel bloquant. À l'aide d'unyield return
ne pas faire en asynchrone. Votre BW devraient faire tous les traitements de données à l'arrière-plan, puis, une fois terminé, la main sur les données traitées à l'INTERFACE utilisateur en une seule étape. Vous êtes à essayer de le remettre dans de nombreuses étapes (c'est à dire à l'aide d'un énumérable) et qui ne va pas au travail. Essayez d'utiliser TPL. Si vous êtes sur .NET 3.5 SP1, alors vous pouvez obtenir le TPL par l'installation de Rx. Il est livré dans il.DoWork
est de typeDoWorkEventHandler
qui ne renvoie rien (void
),il n'est donc pas possible dans votre cas.
Le travailleur doit définir le Résultat de la propriété de DoWorkEventArgs.
Ok, donc j'ai fait quelque chose comme ce qui fait ce que je voulais (certaines variables omises):
et ensuite dans le site d'appel:
Pour les nouveaux lecteurs: la façon la plus élégante pour mettre en œuvre anonyme des itérateurs " (j'. e. imbriqués dans d'autres méthodes) en C#5 est probablement quelque chose comme ce truc génial avec async/await (ne pas être confondu par ces mots-clés, le code ci-dessous est calculé absolument synchrone - voir les détails dans la page du lien):
C#7 (maintenant disponible dans Visual Studio 15 Aperçu) prend en charge fonctions locales, qui permettent à
yield return
: