从另一个线程隐藏/显示Winforms GUI C#

时间:2010-02-03 18:04:57

标签: c# .net winforms show-hide

这篇文章是Way to quickly show/hide WinForms GUI C#的延续,因为在这种特殊情况下它对我不起作用。

我有两个问题:

  • 1是mainAnnounceWindow gui应该启动隐藏,稍后调用时:windowStateChange(“Show”)它应该显示,通过windowStateChange(“Hide”)它应该隐藏。它不能正确地执行,因为当我启动应用程序时,它可见为0.5秒(我看到它闪烁)。有没有办法让它开始隐藏而不会眨眼半秒钟。

  • 2是从myThreadHandler(Queue.Work)调用windowStateChange时无法正常工作。

    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(“Show”)时;从其他线程内部gui显示但不完全..就像我可以看到它想要显示,但事实并非如此。就像一个应用程序的挂起。但是当Thread.Sleep(5000)通过应用程序隐藏时。

通话:

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

没问题。 BaloonTip显示,只是Gui没有正确显示。我做错了什么。

哦,当然我做了一些剪切/粘贴,所以它可能会遗漏一些东西。如果有必要添加一些东西让我知道。

关于,

MadBoy

2 个答案:

答案 0 :(得分:1)

您的问题是您正在从非ui线程访问ui对象,这是不允许的。您需要将一个包含您要执行的操作的委托传递给其中一个ui控件(可能是您的表单对象)上的Invoke或BeginInvoke方法。

答案 1 :(得分:1)

问题是你的主线程被锁定了,因为你添加了这个:

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