Click here to Skip to main content
15,892,059 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
See more:
I need to transfer data from a form minimised with an icon in the system tray to a target form in the same appication. This has been achieved by the use of delegates. Now I would like to Hide() the target form when the scource is idle and Show() when data is scheduled for sending but the target hangs on the Form.Hide/Show call. Has anyone any ideas how to achieve this please.
Posted
Comments
[no name] 7-Nov-11 20:04pm    
How are you showing/hiding the forms?
Clive Porter 10-Nov-11 6:50am    
Many thanks SAKryukov

The question is not clear and full of unrelated information while some related information is probably missing. Basically, all the calls to any UI methods/properties should be done only from the UI thread.

So, if you want to cause showing or hiding the form safely from any thread, you should do this:
C#
static void ShowHideForm(Form form, bool show /* otherwise hide */) {
    if (form.InvokeRequired) {
        form.Invoke(new Action<Form, bool>((formInstance, isShow) => {
            if (isShow)
                formInstance.Show();
            else
                formInstance.Hide();
        }), form, show);
    } else {
        if (show)
            form.Show();
        else
            form.Hide();
    } //if
} //ShowHideForm


Instead of Invoke which waits for processing of the delegate in the UI thread event cycle, you can use non-bloking BeginInvoke which will return immediately when a delegate instance and parameters for its call are posted to the queue of the UI thread, see my references below.

The check of InvokeRequired is not really required: this code will work if only the invocation method is used (first branch under this condition). Non-invocation branch (direct call) will be just more effective when called from UI thread. There is another case when only an invocation part is needed: when you are sure that the code above will be called only from a non-UI thread. Again, it will work from any thread, but it would be less effective if called from (the same) UI thread.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
Comments
Sander Rossel 10-Nov-11 7:20am    
My 5 :)
Sergey Alexandrovich Kryukov 10-Nov-11 11:14am    
Thank you, Naerling.
--SA
I modfied code to

Delegate Sub ShowHideForm_Delegate(ByVal pform As Form, _
                                   ByVal pshow As Boolean)

Private Sub ShowHideForm_ThreadSafe(ByVal pform As Form, _
                                    ByVal pshow As Boolean)
If pform.InvokeRequired Then
     Dim MyDelegate As New ShowHideForm_Delegate(AddressOf ShowHideForm_ThreadSafe)
        pform.Invoke(MyDelegate, New Object() {[pform], [pshow]})
    Else
        If (pshow) Then
            pform.Show()
        Else
            pform.Hide()
        End If
    End If
End Sub


This works fine although there is an issue with Mouse Click event on target
form(pform)

Thanks again)
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900