10
votes

Puis-je disposer d'un threading.Timer dans son rappel?

J'utilise threading.timer , comme: xxx

Comment puis-je disposer cette minuterie à l'intérieur d'un rappel. ou renforcement? MISE À JOUR: Permettez-moi d'expliquer la situation. Je veux essayer d'appeler la méthode "Enregistrer", alors qu'elle jette une exception. Si cela fonctionne, j'ai besoin d'arrêter la minuterie.


3 commentaires

Avez-vous essayé d'assigner à une variable, puis à accéder à la variable?


Pourquoi ne pouvez-vous pas simplement envelopper le minuteur dans un en utilisant la déclaration ?


@Cody parce que la minuterie peut être éliminée plus tôt que prévu.


5 Réponses :


16
votes

Essayez ceci:

Timer timer = null;
timer = new Timer(new TimerCallback(y =>
{    
    try    
    {
        Save(Read(DateTime.Now));        
        // here i want to dispose this timer
        timer.Dispose();    
    }    
    catch    
    {    
    }
}));
timer.Change(10000, 10000);


7 commentaires

Wow, ici, j'essaie de faire cette question compliquée. La solution évidente est en effet un éliminer la déclaration . J'ai supposé que cela était déjà exclu comme "pas une option" pour une raison quelconque.


Je suppose que c'était trop évident :-)


Ma perte, votre gain. J'essaie souvent de rendre les choses trop compliquées. +1 pour la solution correcte, mais simple,.


Je ne pense pas que ce soit à 100% de fil, la série d'événements suivants (ridiculement improbable) pourrait théoriquement se produire: 1. Minuterie créée. 2. 3. Feu de rappel sur ThreadPool 4. 5. L'affectation se produit. La manière thread-Safe serait probablement de créer la minuterie avec des délais d'attente infinis pour forcer l'affectation avant le rappel ThreadPool, puis utilisez le changement () pour définir les propriétés récurrentes.


@Chuu: Bon point. Je pense que tu as raison. J'ai changé ma réponse en conséquence.


@Jakobchristensen Resharper donne l'avertissement suivant "Accès à la fermeture modifiée"? Coffre-fort d'ignorer l'avertissement dans ce cas?


@ user2383728 Resharper se plaint probablement que Minuterie est modifié en dehors du délégué après avoir créé une fermeture autour de la minuterie . Vous pouvez ignorer l'avertissement dans ce cas.



2
votes

Vous devez conserver la référence de la minuterie dans une variable -

public class MyClass
{
    private Timer _timer;

    public void StartTimer()
    {
        _timer =  new Timer(new TimerCallback(y=>{
                            try
                            {
                                Save(Read(DateTime.Now));
                                _timer.Dispose();
                            }
                            catch { 

                            }
                        }),null,100000,10000);
    }



}


0 commentaires

0
votes

Vous devrez stocker une référence à la minuterie quelque part et transmettre que dans l'état de l'état de la minuterie elle-même. Essayez de créer une classe quelque chose comme ceci: xxx

puis utilisez-le dans votre méthode, comme: xxx


0 commentaires

3
votes

Voici une meilleure façon de le faire. Lorsque vous utilisez le constructeur avec un seul param (Timercallback), l'état transmis au rappel sera la minuterie elle-même. XXX

Voici un exemple de la DOCS MSDN: < Pré> xxx

http: //msdn.microsoft.com/en-us/library/ms149618(v=VS.110).aspx


0 commentaires

0
votes

Prenez soin de vous si vous utilisez Multhreading ou multitâche! Si tel est le cas, vous êtes ici, vous êtes le code et une substitution d'un extenseur de méthode AnnexeDeter (.NET 4.0):

       private static object syncObj = new object();

       public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null)
    {
        if (timeoutMilliseconds == 0) return; // No timeout

        if (source == null)
        {
            throw new NullReferenceException();
        }
        if (timeoutMilliseconds < -1)
        {
            throw new ArgumentOutOfRangeException("timeout");
        }
        Timer timer = new Timer(delegate(object self)
        {
            lock (syncObj)
            {
                try
                {
                    if (null != code)
                        code.Invoke();
                    source.Cancel();

                    ((IDisposable)self).Dispose();
                }
                catch (ObjectDisposedException)
                {
                }                   
            }
        });
        timer.Change(timeoutMilliseconds, -1);
    }
}


0 commentaires