Existe-t-il une méthode simple et agréable pour retarder un appel de fonction tout en laissant le thread continuer à s'exécuter?
par exemple
public void foo()
{
// Do stuff!
// Delayed call to bar() after x number of ms
// Do more Stuff
}
public void bar()
{
// Only execute once foo has finished
}
Je suis conscient que cela peut être réalisé en utilisant un minuteur et des gestionnaires d'événements, mais je me demandais s'il existe un moyen c # standard pour y parvenir?
Si quelqu'un est curieux, la raison pour laquelle cela est nécessaire est que foo () et bar () sont dans des classes (singleton) différentes que j'ai besoin de s'appeler dans des circonstances exceptionnelles. Le problème étant que cela se fait à l'initialisation, donc foo doit appeler bar qui a besoin d'une instance de la classe foo qui est en cours de création ... d'où l'appel retardé à bar () pour s'assurer que foo est complètement instancié. sent presque le mauvais design!
ÉDITER
Je prendrai les points sur la mauvaise conception en délibéré! J'ai longtemps pensé que je pourrais être en mesure d'améliorer le système, cependant, cette situation désagréable ne se produit que lorsqu'une exception est levée, à tous les autres moments, les deux singletons coexistent très bien. Je pense que je ne vais pas me mêler de vilains patters asynchrones, je vais plutôt refactoriser l'initialisation d'une des classes.
Awake
etStart
phases. Dans laAwake
phase, vous vous configurez et à la fin de cette phase, tous les objets sont initialisés. Pendant laStart
phase, les objets peuvent commencer à communiquer entre eux.Réponses:
Merci au C # 5/6 moderne :)
la source
J'ai cherché quelque chose comme ça moi-même - j'ai trouvé ce qui suit, bien qu'il utilise une minuterie, il ne l'utilise qu'une seule fois pour le délai initial et ne nécessite aucun
Sleep
appel ...(merci à Fred Deschenes pour l'idée de disposer la minuterie dans le rappel)
la source
timer
variable locale à partir du lambda qui est liée à l'objet déléguécb
entraîne son hissage sur un magasin anon (détail de l'implémentation de la fermeture) qui rendra l'Timer
objet accessible du point de vue du GC tant que leTimerCallback
délégué lui-même sera accessible . En d'autres termes, ilTimer
est garanti que l' objet ne sera pas récupéré jusqu'à ce que l'objet délégué soit appelé par le pool de threads.En plus d'être d'accord avec les observations de conception des commentateurs précédents, aucune des solutions n'était assez propre pour moi. .Net 4 fournit
Dispatcher
et desTask
classes qui rendent Retardement sur le thread courant assez simple:Pour le contexte, j'utilise ceci pour éliminer un
ICommand
lien lié à un bouton gauche de la souris sur un élément de l'interface utilisateur. Les utilisateurs double-cliquent, ce qui cause toutes sortes de ravages. (Je sais que je pourrais aussi utiliserClick
/DoubleClick
handlers, mais je voulais une solution qui fonctionne avec lesICommand
s dans tous les domaines).la source
Il semble que le contrôle de la création de ces deux objets et leur interdépendance doivent être contrôlés de l'extérieur, plutôt qu'entre les classes elles-mêmes.
la source
C'est en effet une très mauvaise conception, et encore moins singleton en soi est une mauvaise conception.
Cependant, si vous avez vraiment besoin de retarder l'exécution, voici ce que vous pouvez faire:
Cela sera cependant appelé
bar()
sur un thread séparé. Si vous avez besoin d'appelerbar()
dans le thread d'origine, vous devrez peut-être déplacer l'bar()
invocation vers leRunWorkerCompleted
gestionnaire ou faire un peu de piratage avecSynchronizationContext
.la source
Eh bien, je devrais être d'accord avec le point de "conception" ... mais vous pouvez probablement utiliser un moniteur pour faire savoir à l'un quand l'autre a dépassé la section critique ...
la source
Usage:
la source
Je pensais que la solution parfaite serait d'avoir une minuterie pour gérer l'action retardée. FxCop n'aime pas quand vous avez un intervalle de moins d'une seconde. Je dois retarder mes actions jusqu'à APRÈS que mon DataGrid ait terminé le tri par colonne. J'ai pensé qu'une minuterie à un coup (AutoReset = false) serait la solution, et cela fonctionne parfaitement. ET, FxCop ne me laissera pas supprimer l'avertissement!
la source
Cela fonctionnera soit sur les anciennes versions de .NET
Cons: s'exécutera dans son propre thread
Usage:
la source
Il n'y a pas de méthode standard pour retarder un appel à une fonction autre que d'utiliser une minuterie et des événements.
Cela ressemble au modèle anti-GUI consistant à retarder un appel à une méthode afin que vous puissiez être sûr que le formulaire a terminé sa mise en page. Pas une bonne idée.
la source
S'appuyant sur la réponse de David O'Donoghue, voici une version optimisée de Delayed Delegate:
La classe pourrait être légèrement améliorée en utilisant une clé unique pour les délégués. Parce que si vous ajoutez le même délégué une deuxième fois avant le déclenchement du premier, vous risquez de rencontrer un problème avec le dictionnaire.
la source
la source