2011-08-12 3 views
3

aujourd'hui j'ai rencontré un problème très intéressant, que j'ai été heureusement capable de résoudre très rapidement, mais j'aimerais connaître la nature du problème.Minuterie mystère - Forms.Timer vs Threading.Timer

J'ai écrit une classe de contrôle qui gère les actions du joystick. Je voulais commencer une action et démarrer la minuterie sur le bouton clic et après l'intervalle de temps pour arrêter cette action.

J'ai une classe (pseudo-code) qui ressemble à ceci:

public class Joystick : UserControl 
{ 
    private Form.Timer timer; //or System.Threading.Timer 
    public void Init() 
    { 
     timer.Tick += new EventHandler(timerCallback) //Threading.Timer(timerCallback) 
     timer.Stop();//timer.Change(Timeout.Infinite, Timeout.Infinite); 
    } 

    public void ButtonCallback() 
    { 
     StartSomething(); 
     timer.Stop(); 
     timer.Start(); //timer.Change(500, Timeout.Infinite); 
    } 

    public void timerCallback() 
    { 
    StopSomething(); 
    timer.Stop();//timer.Change(Timeout.Infinite, Timeout.Infinite); 
    } 
} 

J'ai deux applications, l'une est très simple (juste une forme), la deuxième est plus complexe, mais derrière cette complexité est encore un formulaire ordinaire (bien DotNetMagicForm) contenant ce UserControl. La gestion du code est absolument identique dans les deux applications, mais dans l'application plus complexe, timerCallback() n'a jamais été appelé. Dans le simple tout a bien fonctionné. L'init a été appelé dans les deux cas (breakpoint). Même si j'affecte timerCallback dans ButtonCallback - le timerCallback n'a toujours pas été appelé.

J'ai suivi un conseil d'un de mes collègues et l'ai réécrit en utilisant Threading.Timer au lieu de Forms.Timer et soudainement il a commencé à fonctionner dans les deux applications. Aucun d'entre nous ne sait pourquoi.

Je sais que ma question est assez vague, mais quelle pourrait être la source de ce problème?

Merci

Répondre

5

Le Threading.Timer ne pas utiliser une pompe de message d'interface utilisateur pour callback la tique. Il utilise un thread ThreadPool pour le faire.

Les temporisateurs d'interface utilisateur affichent simplement des messages dans la pompe de message du formulaire pour solliciter le rappel. Votre forme magique d'arrière-plan ne recevait tout simplement pas ces messages. Je ne suis jamais sûr pourquoi cependant, peut-être parce que le formulaire est sur un autre fil sans pompe de message, ou des formes inactives ne traitent pas la pompe peut-être.

1

Avez-vous eu un coup d'œil à l'article this comparant les différentes classes d'horloge .NET

0

Windows Forms minuterie est supposé envoyer WM_TIMER à la file d'attente de messages. Votre file d'attente de messages peut être trop occupée avec le traitement d'autres messages de Windows ou le message n'a peut-être pas été soumis en premier lieu. Vous pouvez utiliser un outil comme Spy ++ pour comprendre ce qui se passe (il doit être installé dans le studio visuel).