Form creation crisis!!!
-
Hi! I have a form(constitued my linklabels) that creates other child forms.When i click on one of the form1 elements the "spawnned" child works just fine(creation starts in the event handler). In my application i have an object that has threads that comunicate with the main form by means of an event.When something happens in the thread i raise in it an event and a handler in form1 gets the request.The thing is that when i use the same function to create the new form, it just hangs(after a while the window enters in a NOT RESPOND state!).Any hint on this?Is it because the thread doesn't terminate and the form hangs waiting for the thread to terminate?
-
Hi! I have a form(constitued my linklabels) that creates other child forms.When i click on one of the form1 elements the "spawnned" child works just fine(creation starts in the event handler). In my application i have an object that has threads that comunicate with the main form by means of an event.When something happens in the thread i raise in it an event and a handler in form1 gets the request.The thing is that when i use the same function to create the new form, it just hangs(after a while the window enters in a NOT RESPOND state!).Any hint on this?Is it because the thread doesn't terminate and the form hangs waiting for the thread to terminate?
carlos_rocha wrote: In my application i have an object that has threads that comunicate with the main form by means of an event.When something happens in the thread i raise in it an event and a handler in form1 gets the request.The thing is that when i use the same function to create the new form, it just hangs(after a while the window enters in a NOT RESPOND state!). In this scenario you should use
Control.Invoke()
[^] to marshal the execution of the event handler to the thread that owns form1. Multithreaded Windows Forms Control Sample[^] explains why this is necessary (see also Asynchronous Execution in Visual Basic .NET[^] for a well documented code sample). Best regards Dennis -
carlos_rocha wrote: In my application i have an object that has threads that comunicate with the main form by means of an event.When something happens in the thread i raise in it an event and a handler in form1 gets the request.The thing is that when i use the same function to create the new form, it just hangs(after a while the window enters in a NOT RESPOND state!). In this scenario you should use
Control.Invoke()
[^] to marshal the execution of the event handler to the thread that owns form1. Multithreaded Windows Forms Control Sample[^] explains why this is necessary (see also Asynchronous Execution in Visual Basic .NET[^] for a well documented code sample). Best regards DennisHi! First of all, thank you for your reply.I'm a bit new to vb.net so i didn't quite understand what you said, or i didnt' explain my problem correctly.I haev the main form, FORM1 that has an object that contains a thread.When something happens in that thread i raise and event to FORM1 and the handler calls a function that creates the form. The sample in msdn is a bit confusing.Where should i use the invoke() method? Directly in FORM1 or in the thread?
-
Hi! First of all, thank you for your reply.I'm a bit new to vb.net so i didn't quite understand what you said, or i didnt' explain my problem correctly.I haev the main form, FORM1 that has an object that contains a thread.When something happens in that thread i raise and event to FORM1 and the handler calls a function that creates the form. The sample in msdn is a bit confusing.Where should i use the invoke() method? Directly in FORM1 or in the thread?
carlos_rocha wrote: I haev the main form, FORM1 that has an object that contains a thread.When something happens in that thread i raise and event to FORM1 and the handler calls a function that creates the form. Well, if I understood you correctly you've got an event handler like this which is called in another thread (i.e. other than the thread that owns form1 and most likely runs the standard application message loop):
Private Sub SomeEventHandler()
someObjVar = New Form2()
someObjVar.Show()
End SubThe problem is that you're not supposed to do this in any thread. In general only the thread that owns a control (meaning that originally created it) should manipulate it. The easiest way is to create any controls (that includes forms and usercontrols) in the same thread. Therefore you need to make a cross-thread call if you want to do something with your UI from another thread. To find out if the call needs to be marshalled you use the
Control.InvokeRequired
Property[^] and end up with something like this:Private Sub SomeEventHandler()
If Me.InvokeRequired Then
Me.Invoke(New appropriateDelegate(AddressOf Me.SomeEventHandler))
Else
someObjVar = New Form2()
someObjVar.Show()
End If
End SubI recommend you keep on reading the MSDN articles and references and come back and ask again whenever you don't understand something. Threading is a straining business and if you don't know what your doing you might end up with some strange behaviour (for example if you don't have a good concept for handling exceptions or call some control's methods ;-)). Best regards Dennis
-
carlos_rocha wrote: I haev the main form, FORM1 that has an object that contains a thread.When something happens in that thread i raise and event to FORM1 and the handler calls a function that creates the form. Well, if I understood you correctly you've got an event handler like this which is called in another thread (i.e. other than the thread that owns form1 and most likely runs the standard application message loop):
Private Sub SomeEventHandler()
someObjVar = New Form2()
someObjVar.Show()
End SubThe problem is that you're not supposed to do this in any thread. In general only the thread that owns a control (meaning that originally created it) should manipulate it. The easiest way is to create any controls (that includes forms and usercontrols) in the same thread. Therefore you need to make a cross-thread call if you want to do something with your UI from another thread. To find out if the call needs to be marshalled you use the
Control.InvokeRequired
Property[^] and end up with something like this:Private Sub SomeEventHandler()
If Me.InvokeRequired Then
Me.Invoke(New appropriateDelegate(AddressOf Me.SomeEventHandler))
Else
someObjVar = New Form2()
someObjVar.Show()
End If
End SubI recommend you keep on reading the MSDN articles and references and come back and ask again whenever you don't understand something. Threading is a straining business and if you don't know what your doing you might end up with some strange behaviour (for example if you don't have a good concept for handling exceptions or call some control's methods ;-)). Best regards Dennis
Hi again! ok, i hope u don't get mad at me but...maybe i didn't explain my problem correctly(again). When you say "Well, if I understood you correctly you've got an event handler like this which is called in another thread (i.e. other than the thread that owns form1 and most likely runs the standard" i mean, the event handler is in FORM1 but the event is in another thread. When you say "Therefore you need to make a cross-thread call if you want to do something with your UI from another thread" do you mean direct manipulations?Because i'm not changig things directly from the other thread, i call the event in that thread so that the handler in the FORM1(that has the control) creates the new form.Shouldn't his work? I'm completly lost :P
-
Hi again! ok, i hope u don't get mad at me but...maybe i didn't explain my problem correctly(again). When you say "Well, if I understood you correctly you've got an event handler like this which is called in another thread (i.e. other than the thread that owns form1 and most likely runs the standard" i mean, the event handler is in FORM1 but the event is in another thread. When you say "Therefore you need to make a cross-thread call if you want to do something with your UI from another thread" do you mean direct manipulations?Because i'm not changig things directly from the other thread, i call the event in that thread so that the handler in the FORM1(that has the control) creates the new form.Shouldn't his work? I'm completly lost :P
carlos_rocha wrote: ok, i hope u don't get mad at me but... No. Not yet. ;-) carlos_rocha wrote: i mean, the event handler is in FORM1 but the event is in another thread. Well, at least I think I understood you correctly. Regarding your event handler: an event handler, no matter to which class it belongs, is ultimately nothing else than a piece of code. Let's say you start with thread A. A is your main thread. It creates the application message loop, a form and a second thread B. If this thread B wants to raise an event, it calls the delegates which were registered thru the appropriate event. Accordingly this delegate will be executed in thread B no matter that it was originally registered in thread A. So just because an object was created in thread X does not mean that every call of a method of the particular object will be automatically executed in thread X. carlos_rocha wrote: Because i'm not changig things directly from the other thread, i call the event in that thread so that the handler in the FORM1(that has the control) creates the new form. Yeah, form1 creates the new form, but in the "wrong" thread (as I called it, thread B). So the "wrong" thread will be the owner of the new form instance. carlos_rocha wrote: Shouldn't his work? Counter question: have you already tried to get it to run with
Control.Invoke()
? Best regards Dennis -
carlos_rocha wrote: ok, i hope u don't get mad at me but... No. Not yet. ;-) carlos_rocha wrote: i mean, the event handler is in FORM1 but the event is in another thread. Well, at least I think I understood you correctly. Regarding your event handler: an event handler, no matter to which class it belongs, is ultimately nothing else than a piece of code. Let's say you start with thread A. A is your main thread. It creates the application message loop, a form and a second thread B. If this thread B wants to raise an event, it calls the delegates which were registered thru the appropriate event. Accordingly this delegate will be executed in thread B no matter that it was originally registered in thread A. So just because an object was created in thread X does not mean that every call of a method of the particular object will be automatically executed in thread X. carlos_rocha wrote: Because i'm not changig things directly from the other thread, i call the event in that thread so that the handler in the FORM1(that has the control) creates the new form. Yeah, form1 creates the new form, but in the "wrong" thread (as I called it, thread B). So the "wrong" thread will be the owner of the new form instance. carlos_rocha wrote: Shouldn't his work? Counter question: have you already tried to get it to run with
Control.Invoke()
? Best regards DennisMan, you explained the problem very well!!! i'm sorry, i haven't tried the control.invoke() i will test now.Stay tuned (please) :D
-
Man, you explained the problem very well!!! i'm sorry, i haven't tried the control.invoke() i will test now.Stay tuned (please) :D
Hi! You're the man. Control.Invoke() worked just fine. Before i use it i do a test using InvokeRequired(), if it gives out true it's because i'm not on the thread that initially created the form, so i call invoke(). Thank you very much.