0

I'm working on a legacy application which has sprinklings of Application.DoEvents here and there. I'm fully aware that this is frowned upon due to re-entrancy issues, but re-factoring isn't currently an option.

An issue has started to occur where DoEvents never exits. The UI is responsive (I can see UI thread activity in the user logs) so DoEvents seems to be pumping the messages, but for some reason it never completes. Unfortunately this DoEvents is in the main data-processing component, which means this stops processing server responses as it's stuck on the DoEvents line.

We have Stopwatch trace which tells how long the DoEvents ran for - staggeringly I got a log where it said it was running for 188267770 milliseconds, which is 52 hours (gulp). It seemed to get into this state at about 3am on a Saturday, until the user came in on Monday and shut the app down (not killing the process, I can see the GUI thread trace closing things gracefully), at which point the DoEvents completes and the timer data is logged (so something which happens during shutdown must convince DoEvents to complete).

Of course, this only happens on the production user's machines, and not on my dev box :)

Has anyone ever seen a similar problem to this?

I've decompiled DoEvents and also how Conrol.BeginInvoke pushes method delegates onto the GUI thread using the Windows message queue, but I cannot see how DoEvents can get stuck like this, and keep the UI responsive.

Source control diff is also not an option since there's been around 30 versions since the last 'good' version the users had, and this new version with the problem - so about 200 files have changed.

Many thanks Paul

Paul Green
  • 19
  • 4
  • Don't use `DoEvents` [see this](http://blog.codinghorror.com/is-doevents-evil) – SimpleVar Mar 31 '15 at 01:06
  • 2
    That's one great story..it have plot and characters - where is the code? – G.Y Mar 31 '15 at 01:10
  • I'd suggest logging the "main data-processing component" code, and review the log to see the long long list that your problem is. It might help you identify the nature of the problem. – SimpleVar Mar 31 '15 at 01:22

2 Answers2

1

For the loop to keep running there must be messages on the message queue. So I assume that there is a message that when dispatched then causes another message to be put on the queue. And so forth forever.

Do you have any background processing that causes this type of behaviour? Posting another message to continue processing? Is there an event in the system that can occur that when processed could simply occur immediately again?

The other alternative is that one of the messages is itself creating a nested message loop. For example, showing a dialog would cause a nested message loop that does not finish until the dialog is removed. Does your app try and show a dialog that will then not be dismissed for some reason?

Impossible for us to tell you the answer given the number of possibilities.

Phil Wright
  • 22,580
  • 14
  • 83
  • 137
  • _"For the loop to keep running there must be messages on the message queue"_ -- what do you mean by that? A message loop will block waiting for new messages if none are present, but I wouldn't say that the loop isn't running per se, any more than I'd say a `for` or `while` loop is no longer running just because something inside the loop is waiting on something else. – Peter Duniho Mar 31 '15 at 01:16
  • He means that as long as there are messages on the queue, the `DoEvents` will continue execution, which suggests that messages are added to the queue as part of the execution of the `DoEvents` loop, indefinitely. – SimpleVar Mar 31 '15 at 01:18
  • Application.DoEvents() will run the message loop only as long as there are messages to be dispatched. It uses PeekMessage internally to check if there is another message available for dispatch and when there is not, it exits. Hence for the method to not return means that there is constantly one more message to process. – Phil Wright Mar 31 '15 at 01:20
  • I appreciate this is pretty difficult to pin down given the complexity. Having run out of ideas I thought I'd try SO as I usually find what I'm looking for here. I'll keep digging...... – Paul Green Mar 31 '15 at 02:38
1

After much digging I finally found the cause - System.Windows.Forms.Timer.

Basically two or more Timers can cause a DoEvents() call to never end. Whilst processing one timer WM_TIMER message, another timer can post its WM_TIMER message, which is then processed by DoEvents, as that is being processed the first Timer will post, and so on.

The app I'm working on has about 8 Timers I've found so far....

But really, DoEvents is the real culprit so I plan to re-factor to get rid of it.

Paul Green
  • 19
  • 4