Odd Windows Forms Behavior

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
I have to modify a VB.net windows forms application to add another form to it. Since I don't have much experience in VB, I just wrote the new form in C# and imported it into the VB project. The VB project has one Main form that holds most of the application logic, including a timer (System.Windows.Forms.Timer) that fires every 100 or 200ms to update data.

The odd behavior I'm experiencing is whenever I show my new form (using Form.Show), this timer stops firing until I close the child window. I put my call to myform.show() right after a call to existingform.show(), but the existing form doesn't impact the timer. The only differences I can find are that my form is C#, and it resides in a separate assembly. I've scoured the source code, and there are no references to timer.Stop() or timer.Enabled=false, so I really don't know what could be causing this problem. Any WinForms gurus have ideas for places too look?

EDIT: I should add that even after my form is shown, the form holding the problem timer stays responsive (I can click components and their OnClick handlers will still fire, it's just the one timer that stops working).
 
Last edited:

WannaFly

Platinum Member
Jan 14, 2003
2,811
1
0
I made a _VERY_ basic mock up doing exactly what you are describing, and it seems to be working fine. So there must be something else specific to your app that is blocking/stopping the timer.

Is it an MDI application by chance? If you put a breakpoint on the timer fire event, does it just never hit? It sounds like it might be doing showdialog, but you say that the other forms events work fine...I'm stumped.

What Visual Studio are you using?

edit:
are you sure the timer is enabled? If you put the form call after exisitingform.show, maybe it never gets enabled?
 
Last edited:

KIAman

Diamond Member
Mar 7, 2001
3,342
23
81
That's odd. Try using System.Timers.Timer and set your SynchronizingObject to the parent form.
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
I made a _VERY_ basic mock up doing exactly what you are describing, and it seems to be working fine. So there must be something else specific to your app that is blocking/stopping the timer.

Is it an MDI application by chance? If you put a breakpoint on the timer fire event, does it just never hit? It sounds like it might be doing showdialog, but you say that the other forms events work fine...I'm stumped.

What Visual Studio are you using?

edit:
are you sure the timer is enabled? If you put the form call after exisitingform.show, maybe it never gets enabled?

Part of the problem is that the existing VB code is very poorly written (tons of globals, no structure, etc), so I can't guarantee that something convoluted isn't going on, but here was my debug procedure:

  • Start Application
  • Place Breakpoint in the timer "OnTick" handler for the main form (immediately breaks)
  • Remove Breakpoint
  • Click button to show 2 forms (using Form.Show and NOT ShowDialog)
  • Replace Breakpoint (nothing)
  • Close my new form via the 'X' in the top right (immediately breaks), the other child form is still shown.

Here's the show code that shows the forms:
Code:
Private Sub Ctl3dPushButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Ctl3dPushButton3.Click
    myForm.Show()
    oldForm.Show()
End Sub

Commenting out "myForm.Show()" means the timer always works, which means there has to be something in my form that it doesn't like. All the properties are defaults so I'm kind of lost as to what the issue is. Currently I'm redoing a lot of the VB in C# (and cleaning it up along the way). There's probably something stupid I'm overlooking, but it's easy to get lost in spaghetti code :p
 

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
May I suggest you wireup an event to the stop event for the timer? Something simple and a breakpoint, so that if something is stopping the timer, you can track what? Maybe something on that and the dispose method, in case something is just flat out killing the timer.
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
May I suggest you wireup an event to the stop event for the timer? Something simple and a breakpoint, so that if something is stopping the timer, you can track what? Maybe something on that and the dispose method, in case something is just flat out killing the timer.

Good suggestion... I'll give that a shot.
 

linkgoron

Platinum Member
Mar 9, 2005
2,579
1,233
136
I've has the same problem with a win-forms application. I believe I solved it with threading.

This might be a stupid idea,but have you tried opening the new form in a new Thread? It may not be ideal, but it might just solve your problem without wasting much time.
 

Cogman

Lifer
Sep 19, 2000
10,284
138
106
I think your issue might be related to the windows callback function/message pump. The problem is, both applications are potentially setting up their own message callback functions and message pumps in different ways. So what is probably happening is when you call the C# program, it gets caught in the C# message pump. This prevents the VB message pump from running (until the C# code closes down.)

The fix? Run it in a new thread.
 

Cogman

Lifer
Sep 19, 2000
10,284
138
106
Code:
void someCallbackFunc()
{
   doStuff();
}

void main()
{
   CreateWindow();
   while (GetMessage())
   {
      TranslateMessage();
      DispatchMessage();
   }
}

This is what the typical message pump looks like. in c++ (ish. Not true windowing code, but close)

C# and VB go to great lengths to try and hide this. However, it is built into the kernel, so any windows program is going to have this sort of message pump in it.
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
I think your issue might be related to the windows callback function/message pump. The problem is, both applications are potentially setting up their own message callback functions and message pumps in different ways. So what is probably happening is when you call the C# program, it gets caught in the C# message pump. This prevents the VB message pump from running (until the C# code closes down.)

Sounds logical, but wouldn't all the other click events get rerouted to the incorrect Message Pump is what you say is true? The Timer.OnTick event is the only one lost in oblivion right now.
 

Cogman

Lifer
Sep 19, 2000
10,284
138
106
Sounds logical, but wouldn't all the other click events get rerouted to the incorrect Message Pump is what you say is true? The Timer.OnTick event is the only one lost in oblivion right now.

Well, that depends on how the .Net pump is being implemented. Its completely possible that the message is still getting dispatched to the correct place, just the timer is never being reached.

Give it a shot. I'll be if you put a message box pop-up after the calling of the C# application that it won't fire until the C# thing finishes.
 

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
Well, that depends on how the .Net pump is being implemented. Its completely possible that the message is still getting dispatched to the correct place, just the timer is never being reached.

Give it a shot. I'll be if you put a message box pop-up after the calling of the C# application that it won't fire until the C# thing finishes.

Couple things here:
  • Showing form on new thread seems to work using the code below.
  • If I place MessageBox.Show() right after myform.Show(), no message box is visible, but I can't interact with the other forms anymore (just as if a MessageBox were showing).

VB code to spawn new thread:

Code:
Dim myformThread as System.Threading.Thread

Private Sub showMyForm()
    System.Windows.Forms.Application.Run(myform)
End Sub

Private functionToDisplayMyForm()
    ....
    oldform.Show()
    myformThread = new System.Threading.Thread(AddressOf functionToDisplayMyForm)
    myformThread.Start()
    ....
End Sub

I realize that needs tweaking so that I don't crash if I call "functionToDisplayMyForm" multiple times in a row, but it does work (as does the messagebox idea). My understanding is that I'll need to still call Application.Run on the new thread because this is what sets up the messaging loop.
 
Last edited: