Скрыть / показать Winforms GUI C # из другого потока - PullRequest
0 голосов
/ 03 февраля 2010

Этот пост является продолжением Способ быстро показать / скрыть графический интерфейс WinForms C # , так как он не работает для меня в данном конкретном случае.

У меня 2 проблемы:

  • 1 - это то, что графический интерфейс mainAnnounceWindow должен начинаться скрытым, а затем при вызове: windowStateChange ("Show") должен показываться, а windowStateChange ("Hide") должен скрываться Это не делает это должным образом, так как когда я запускаю приложение, оно видимо в течение 0,5 с (я вижу, что оно мигает). Есть ли способ заставить его начать скрытым и не мигать в течение полсекунды.

  • 2 заключается в том, что windowStateChange не работает должным образом при вызове из 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();
    
    }
    }
    

Другой класс:

  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
            }
        }
    }

} * * тысяча двадцать-один

Проблема с:

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

Когда я вызываю Program.windowStateChange («Показать»); изнутри другой поток показывает графический интерфейс, но не совсем .. как будто я вижу, что он хотел бы показать, но это не так. Как зависание приложения. Но когда Thread.Sleep (5000) проходит, приложение скрывается.

Призвание:

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

Нет проблем. BaloonTip показывает, просто Gui не отображается должным образом. Что-то я делаю не так.

О, и, конечно, я сделал несколько вырезок / вставок, чтобы они могли пропустить некоторые вещи. Если нужно что-то добавить, дайте мне знать.

С уважением,

MadBoy

Ответы [ 2 ]

1 голос
/ 03 февраля 2010

Проблема в том, что ваш основной поток заблокирован, потому что вы добавили:

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

Это не позволит оконному потоку получать и обрабатывать сообщения Windows (например, показывать и скрывать) соответствующим образом.

Вы также захотите использовать mainAnnounceWindow.Show(), а не mainAnnounceWindow.ShowDialog(), так как это предотвратит правильный возврат элемента управления в основной поток. Вы должны просто позвонить Application.Run(mainAnnounceWindow) в своей основной программе:

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);
}
1 голос
/ 03 февраля 2010

Ваша проблема в том, что вы обращаетесь к объекту пользовательского интерфейса из не пользовательского потока, что запрещено. Вам нужно передать делегат, заключающий операцию, которую вы хотите выполнить, в методы Invoke или BeginInvoke в одном из элементов управления пользовательского интерфейса (возможно, в вашем объекте формы).

...