views:

464

answers:

5

I'm creating an app that is threaded. I started GUI (Announce : Form) as separate thread.

That window will be very minimalistic with one input box and maybe a button. On another thread there will be Tcp Client running and when it gets info from TcpServer it should pass what it gets into that inputbox and show the gui (and topmost windows). After couple of seconds the gui should hide itself and wait for another tcp msg and so on.

    public void setTextBox(string varText) {
        if (InvokeRequired) {
            textBox.BeginInvoke(new textBoxCallBack(setTextBox), new object[] {varText});
        } else {
            textBox.Text = varText;
        }
    }

This code is used to fill the textBox from the Tcp Thread. The only problem now is getting the window show and hide properly. Been trying many solutions and always something went wrong. Like:

    private void windowStateChange(string varState) {
        if (InvokeRequired) {
            Invoke(new WindowStateChangeCallBack(windowStateChange), new object[] {varState});
        } else {
            if (varState == "Hide") {
                //Hide();
                // TopMost = false;
                //TopMost = varState != FormWindowState.Minimized;
            } else {
                //Show();
                //MessageBox.Show("TEST1");
            }
        }
    }

    public void windowStateChangeDiffrent(FormWindowState varState) {
        if (InvokeRequired) {
            Invoke(new WindowStateChangeCallBack(windowStateChange), new object[] {varState});
        } else {
            WindowState = varState;
           // Hide();
            TopMost = varState != FormWindowState.Minimized;
        }
    }

What would be best aproach to do this (and fastest, as time matters)?

Answer 1 which seems to work:

    private static void windowStateChange(string varState) {
        if (mainAnnounceWindow.InvokeRequired) {
            mainAnnounceWindow.BeginInvoke(new StateCallBack(windowStateChange), new object[] {varState});
        } else {
            if (varState == "Hide") {
                mainAnnounceWindow.Hide();
                mainAnnounceWindow.TopMost = false;
            } else {
                mainAnnounceWindow.Show();
                mainAnnounceWindow.TopMost = true;
            }
        }
    }

Anything bad about it?

+1  A: 

Another approach would be to expose events on your TCP thread object. It could define an event such as RecievedData(...) then the GUI could subscribe to that event and update itself without having to do any InvokeRequired checks etc.
Update: link to C# events tutorial
http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx

TJB
If the TCP thread object is running on a different thread to the UI thread, an event will still call the form on that TCP object thread. InvokeRequired is still required (unless I'm mistaken). (an event is a nicer way to provide notifications though)
You might be right, I'm not sure if the event handler for the gui side would run in the gui thread or not, I'd have to look it up to be sure.
TJB
Could you show example how to do this? Not sure where to start?
MadBoy
@MadBoy added link to events tutorial, that should be a good start
TJB
THanks, found it by myself also :-) WIll work on it.
MadBoy
+1  A: 

you might try

form.Hide();

but make sure that you show/hide the form from the same thread that created them

Steven A. Lowe
+1  A: 
this.Invoke(new MethodInvoker(this.hide()));
Microgen
A: 

Form.Hide() is the right method to hide the form. I remember having issues with Form.Show(), I have a vague memory of having to use Form.Activate() as well to get the form to restore correctly.

You're already dealing with thread marshalling correctly (InvokeRequired and Invoke). You could also use Form.BeginInvoke(), which is an async version of Form.Invoke. That might be faster.

+1  A: 

Making the form hide with form.Hide() should pose no problems.

However I've experienced making the form show again does not always work. So if you're encountering the same problem, you could use something like this:

string RunningProcess = Process.GetCurrentProcess().ProcessName;
Process[] processes = Process.GetProcessesByName(RunningProcess);

int SW_SHOW = 5, SW_HIDE = 0, SW_RESTORE = 9, SW_SHOWNORMAL = 1;

    for (int a = 0; a < processes.Length; a++)
        {
         IntPtr hWnd = processes[a].MainWindowHandle;

         ShowWindowAsync(hWnd, SW_RESTORE);
         ShowWindowAsync(hWnd, SW_SHOWNORMAL);
         ShowWindowAsync(hWnd, SW_SHOW);
         SetForegroundWindow((int)hWnd);
        }

        //Required Win32 API imports           
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
        static extern bool ShowWindowAsync(IntPtr windowHandle, int cmd);

        [System.Runtime.InteropServices.DllImportAttribute("User32.dll")]
        private static extern IntPtr SetForegroundWindow(int hWnd);
Mez
Thanks, i had the problem you describe. Will see if the method i posted in first post will be working fine or not.
MadBoy