2010-02-03 4 views
0

Ce message est la suite de Way to quickly show/hide WinForms GUI C#, car il ne fonctionne pas pour moi dans ce cas particulier.Cacher/Montrer Winforms GUI C# à partir d'un autre fil

J'ai 2 problèmes:

  • 1 est que l'interface utilisateur graphique mainAnnounceWindow devrait commencer caché et plus tard lorsqu'il est appelé par: WindowStateChange ("Show"), il doit montrer, par WindowStateChange ("Masquer") il devrait cacher. Il ne le fait pas correctement car quand je lance l'application, il est visible pendant 0,5 s (je le vois clignoter). Y at-il un moyen de le faire démarrer caché et ne pas cligner une demi-seconde.

  • 2 est que windowStateChange ne fonctionne pas correctement lorsqu'il est appelé depuis myThreadHandler (Queue.Work).

    internal class Program { 
    public delegate void StateCallBack(string varState); 
    public static readonly Announce mainAnnounceWindow = new Announce(); 
    public static readonly Thread myThreadGuiAnnounce = new Thread(showGuiAnnounce); 
    public static readonly Thread myThreadTcpClient = new Thread(threadTcpClient); 
    public static readonly Thread myThreadUdpMonitor = new Thread(threadUdpMonitor); 
    public static readonly Thread myThreadHandler = new Thread(Queue.work); 
    
    public static void Main() 
    { 
        myThreadGuiAnnounce.Start(); 
        myThreadTcpClient.Start(); 
        myThreadUdpMonitor.Start(); 
        myThreadHandler.Start(); 
        windowStateChange("Hide"); 
    
        while (true) { 
         Thread.Sleep(1000); 
        } 
    } 
    public static void windowStateChange(string varState) { 
        if (mainAnnounceWindow.InvokeRequired) { 
         mainAnnounceWindow.Invoke(new StateCallBack(windowStateChange), new object[] {varState}); 
        } else { 
         if (varState == "Hide") { 
          mainAnnounceWindow.Hide(); 
          mainAnnounceWindow.TopMost = false; 
         } else { 
          mainAnnounceWindow.Show(); 
          mainAnnounceWindow.TopMost = true; 
         } 
        } 
    } 
        private static void showGuiAnnounce() { 
        mainAnnounceWindow.ShowDialog(); 
    
    } 
    } 
    

Une autre classe:

public class Queue : IDisposable { 
public static void work() { 
     while (true) { 
      string task = null; 
      lock (locker) 
       if (tasks.Count > 0) { 
        task = tasks.Dequeue(); 
        if (task == null) { 
         return; 
        } 
       } 
      if (task != null) { 
       //MessageBox.Show("Performing task: " + task); 
       Program.mainAnnounceWindow.setLogTextBox(task); 
       Program.mainAnnounceWindow.setLogTrayTip(task); 
       Program.windowStateChange("Show"); 
       Thread.Sleep(5000); // simulate work... 
       Program.windowStateChange("Hide"); 
      } else { 
       wh.WaitOne(); // No more tasks - wait for a signal 
      } 
     } 
    } 

}

Le problème est avec:

   Program.windowStateChange("Show"); 
       Thread.Sleep(5000); // simulate work... 
       Program.windowStateChange("Hide"); 

Quand j'appelle Program.windowStateChange ("Show"); de l'intérieur d'autres fils les spectacles de gui mais pas tout à fait .. comme je peux voir qu'il aimerait montrer, mais ce n'est pas le cas. Comme un coup de l'application. Mais quand Thread.Sleep (5000) passe les masques de l'application.

Vocation:

   Program.mainAnnounceWindow.setLogTextBox(task); 
       Program.mainAnnounceWindow.setLogTrayTip(task); 

n'a pas de problème. Spectacles BaloonTip, juste le Gui ne s'affiche pas correctement. Quelque chose que je fais mal. Oh, et bien sûr, j'ai fait du copier/coller, donc ça risque de rater quelques trucs. S'il est nécessaire d'ajouter quelque chose, faites-le moi savoir.

En ce qui concerne,

MadBoy

Répondre

1

Le problème est que votre thread principal est bloqué, parce que vous avez ajouté ceci:

while (true) { 
    Thread.Sleep(1000); 
} 

Cela empêchera le fil de la fenêtre de réception et de traitement des messages Windows (comme afficher et masquer) de façon appropriée.

Vous devez également utiliser mainAnnounceWindow.Show(), et non mainAnnounceWindow.ShowDialog(), car cela empêchera le contrôle de revenir correctement au thread principal. Vous devez simplement appeler Application.Run(mainAnnounceWindow) dans votre routine principale:

public static void Main()  
{  
    myThreadGuiAnnounce.Start();  
    myThreadTcpClient.Start();  
    myThreadUdpMonitor.Start();  
    myThreadHandler.Start();  

    // Just change your main window's load to hide itself... windowStateChange("Hide");  
    Application.Run(mainAnnounceWindow); 
} 
+0

myThreadGuiAnnounce.Start(); commence le thread private static void showGuiAnnounce() {mainAnnounceWindow.ShowDialog(); } donc en fait, GUI a son propre thread distinct de principal. Donc Threa.Sleep (1000) fait dormir le thread principal et ne fait rien pendant que le gui est dans un autre thread? Ça ne devrait pas marcher? – MadBoy

+0

Ça ne va pas être sûr. Le nouveau thread doit être démarré STA, et si vous utilisez ShowDialog, la fenêtre ne traitera pas les messages et ne pourra pas cacher comme vous le souhaitez. Laissez la fenêtre dans le fil principal, et montrez-le normalement (non-dialogue), et votre code fonctionnera probablement le wya que vous voulez ... –

+0

en effet. Si je n'utilise pas de thread séparé pour créer mainAnnounceWindow .. et que j'utilise Main thread comme thread Gui votre solution fonctionne. Mais si je voudrais avoir le fil principal laissé pour d'autres choses (comme le Thread.Sleep était là, le thread principal ne sortirait pas) – MadBoy

1

Votre problème est que vous accédez à un objet ui d'un fil non ui, ce qui est interdit. Vous devez transmettre un délégué enveloppant l'opération que vous souhaitez exécuter aux méthodes Invoke ou BeginInvoke sur l'un des contrôles ui (peut-être votre objet formulaire).

+0

J'utilise WindowStateChange public static void (string varState) qui utilise Invoke pour entrer dans fil GUi. n'est-ce pas assez? – MadBoy

Questions connexes