50 votes

Détecter si sur le thread d'interface utilisateur dans WPF et Winforms

J'ai écrit une méthode d'assertion Ensure.CurrentlyOnUiThread() , ci-dessous, qui vérifie que le thread actuel est un thread d'interface utilisateur.

  • Cela va-t-il être fiable pour détecter le fil d'interface utilisateur Winforms ?
  • Notre application est mixte WPF et Winforms, comment détecter au mieux un thread d'interface utilisateur WPF valide ?
  • Y a-t-il une meilleure manière de faire cela? Peut-être des contrats de code ?

Assurer.cs

 using System.Diagnostics;
using System.Windows.Forms;

public static class Ensure
{
    [Conditional("DEBUG")]
    public static void CurrentlyOnUiThread()
    {
        if (!Application.MessageLoop)
        {
            throw new ThreadStateException("Assertion failed: not on the UI thread");
        }
    }
}

25voto

Ian Points 13892

Dans WinForms, vous utiliseriez normalement

 if(control.InvokeRequired) 
{
 // Do non UI thread stuff
}

pour WPF

 if (!control.Dispatcher.CheckAccess())
{
  // Do non UI Thread stuff
}

J'écrirais probablement une petite méthode qui utilise une contrainte générique pour déterminer laquelle d'entre elles vous devriez appeler. par exemple

 public static bool CurrentlyOnUiThread<T>(T control)
{ 
   if(T is System.Windows.Forms.Control)
   {
      System.Windows.Forms.Control c = control as System.Windows.Forms.Control;
      return !c.InvokeRequired;
   }
   else if(T is System.Windows.Controls.Control)
   {
      System.Windows.Controls.Control c = control as System.Windows.Control.Control;
      return c.Dispatcher.CheckAccess()
   }
}

23voto

Curtis Points 660

Pour WPF, j'utilise ce qui suit :

 public static void InvokeIfNecessary (Action action)
{
    if (Thread.CurrentThread == Application.Current.Dispatcher.Thread)
        action ();
    else {
        Application.Current.Dispatcher.Invoke(action);
    }
}

La clé est au lieu de vérifier Dispatcher.CurrentDispatcher (qui vous donnera le répartiteur pour le thread actuel), vous devez vérifier si le thread actuel correspond au répartiteur de l'application ou à un autre contrôle.

18voto

Matěj Zábský Points 9179

Pour WPF :

 // You are on WPF UI thread!
if (Thread.CurrentThread == System.Windows.Threading.Dispatcher.CurrentDispatcher.Thread)

Pour les formulaires Win :

 // You are NOT on WinForms UI thread for this control!
if (someControlOrWindow.InvokeRequired)

6voto

Alex Farber Points 19387

Peut-être que Control.InvokeRequired (WinForms) et Dispatcher.CheckAccess (WPF) vous conviennent ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X