2013-03-02 3 views
1

J'essaie de créer un bouton dans wpf vs 2010 qui, lorsque cliqué sur effectuera périodiquement une action, j'ai regardé une tonne de problèmes similaires sur ce site et d'autres, mais le problème est que j'essaie d'appeler un fonction qui prend des captures d'écran d'un kinect, peut obtenir une minuterie pour fonctionner, mais il continue à geler donc plutôt que 10 captures d'écran différentes avec des intervalles de 2,5 secondes Je reçois la même capture d'écran encore et encore, toute aide très appréciée. En ce moment j'utilise une case à cocher au lieu d'un bouton selon quelques conseils que j'ai trouvé ici.Problème de minuterie. .

private void checkBox1_Checked_1(object sender, RoutedEventArgs e) 
    { 

     Stopwatch stopwatch = new Stopwatch(); 

     // Begin timing 
     stopwatch.Start(); 

     // Do something 
     for (int i = 0; i < 60000; i++) 
     { 
      Thread.Sleep(3); 
     } 

     // Stop timing 
     stopwatch.Stop(); 

     take_motions(); 
    } 
+0

Le code que vous avez posté ici est juste chronométrant le temps qu'il faut pour dormir 60k fois à peu près ~ 10ms une pop; le fil de sommeil a une granularité d'environ 10 ms, plus ou moins. – JerKimball

Répondre

0

Il y a une classe de minuterie spécialisée dans WPF qui évite les problèmes de filetage transversal de l'interface utilisateur car il fonctionne dans le thread d'interface utilisateur. Il est la classe DispatcherTimer:

private DispatcherTimer timer; 

public MainWindow() 
{ 
    InitializeComponent(); 

    timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2.5) }; 
    timer.Tick += timer_Tick; 
} 

private void timer_Tick(object sender, EventArgs e) 
{ 
    // take screenshot here 
} 

private void checkBox_Checked(object sender, RoutedEventArgs e) 
{ 
    timer.Start(); 
} 

private void checkBox_Unchecked(object sender, RoutedEventArgs e) 
{ 
    timer.Stop(); 
} 
1

Avec ce code, vous bloquez le fil d'application principal. Cela expliquerait pourquoi vous obtenez la même capture d'écran encore et encore.

Ce que vous devez faire est de démarrer la minuterie dans un thread d'arrière-plan, puis formez que le thread envoie un événement à l'application principale pour prendre une capture d'écran. Cela permettra ensuite à l'application de continuer à fonctionner.

Pour ce faire, vous devez utiliser l'une des classes Timer disponibles. Ils fonctionnent chacun légèrement différemment, mais tous devraient vous permettre de spécifier une méthode à appeler sur chaque tick du timer.

Vous devrez renvoyer un événement à l'interface utilisateur pour éviter les problèmes de croisement.

+0

Cool Je vais essayer ça merci :) – H65

1

Vous devez utiliser la minuterie et exécuter take_motions(); dans un thread séparé:

aTimer = new System.Timers.Timer(10000); 

// Hook up the Elapsed event for the timer. 
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 

// Set the Interval to 2 seconds (2000 milliseconds). 
aTimer.Interval = 2000; 
aTimer.Enabled = true; 

private void checkBox1_Checked_1(object sender, RoutedEventArgs e) 
{ 
    //here call timer start or stop 
} 

private static void OnTimedEvent(object source, ElapsedEventArgs e) 
{ 
    ThreadPool.QueueUserWorkItem(delegate 
    { 
    take_motions(); 
    }); 
}