1

I have a multi-threaded application build in C# using VS2010 Professional. It's quite a large application and we've experienced the classing GUI cross-threading and deadlock issues before, but in the past month we've noticed the appears to lock up when left idle for around 20-30 minutes.

The application is irresponsive and although it will repaint itself when other windows are dragged in front of the application and over it, the GUI still appears to be locked... interstingly (unlike if the GUI thread is being used for a considerable amount of time) the Close, Maximise and minimise buttons are also irresponsive and when clicked the little (Not Responding...) text is not displayed in the title of the application i.e. Windows still seems to think it's running fine.

If I break/pause the application using the debugger, and view the threads that are running. There are 3 threads of our managed code that are running, and a few other worker threads whom the source code cannot be displayed for.

The 3 threads that run are:

  1. The main/GUI thread
  2. A thread that loops indefinitely
  3. A thread that loops indefinitely

If I step into threads 2 and 3, they appear to be looping correctly. They do not share locks (even with the main GUI thread) and they are not using the GUI thread at all. When stepping into the main/GUI thread however, it's broken on Application.Run...

This problem screams deadlock to me, but what I don't understand is if it's deadlock, why can't I see the line of code the main/GUI thread is hanging on?

Any help will be greatly appreciated! Let me know if you need more information...

Cheers,

Roo

-----------------------------------------------------SOLUTION--------------------------------------------------

Okay, so the problem is now solved. Thanks to everyone for their suggestions! Much appreciated! I've marked the answer that solved my initial problem of determining where on the main/UI thread the application hangs (I handn't turned off the "Enable Just My Code" option).

The overall issue I was experiencing was indeed Deadlock, however. After obtaining the call-stack and popping the top half of it into Google I came across this which explains exactly what I was experiencing...

http://timl.net/

This references a lovely guide to debugging the issue...

http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/

This identified a control I was constructing off the GUI thread. I did know this, however, and was marshalling calls correctly, but what I didn't realise was that behind the scenes this Control was subscribing to an event or set of events that are triggered when e.g. a Windows session is unlocked or the screensaver exits. These calls are always made on the main/UI thread and were blocking when it saw the call was made on the incorrect thread. Kim explains in more detail here...

http://krgreenlee.blogspot.com/2007/09/onuserpreferencechanged-hang.html

In the end I found an alternative solution which did not require this Control off the main/UI thread.

That appears to have solved the problem and the application no longer hangs. I hope this helps anyone who's confronted by a similar problem.

Thanks again to everyone on here who helped! (and indirectly, the delightful bloggers I've referenced above!)

Roo

-----------------------------------------------------SOLUTION II--------------------------------------------------

Aren't threading issues delightful...you think you've solved it, and a month down the line it pops back up again. I still believe the solution above resolved an issue that would cause simillar behaviour, but we encountered the problem again.

As we spent a while debugging this, I thought I'd update this question with our (hopefully) final solution:

The problem appears to have been a bug in the Infragistics components in the WinForms 2010.1 release (no hot fixes). We had been running from around the time the freeze issue appeared (but had also added a bunch of other stuff too). After upgrading to WinForms 2010.3, we've yet to reproduce the issue (deja vu). See my question here for a bit more information: '.NET 4.0 and the dreaded OnUserPreferenceChanged Hang'. Hans has given a nice summary of the general issue.

I hope this adds a little to the suggestions/information surrounding the nutorious OnUserPreferenceChanged Hang (or whatever you'd like to call it).

Cheers,

Roo

Community
  • 1
  • 1
Roo
  • 203
  • 1
  • 3
  • 9
  • Have you checked your memory usage? Maybe it is not really deadlocked, just swapping from disk... – Grzenio Aug 19 '10 at 15:06
  • @Grzenio: No; then it wouldn't respond at all. – SLaks Aug 19 '10 at 15:07
  • 4
    What's the callstack inside `Application.Run`? (Disable Just My Code) – SLaks Aug 19 '10 at 15:07
  • 1
    It would be helpful to know what the main thread is doing. – Steven Sudit Aug 19 '10 at 15:08
  • If the form is repainting, then the UI thread is not deadlocked in the classic sense. It sounds more like the mouse events are being swallowed somehow or the form has a modal dialog stuck behind it. Is the application still responsive to keyboard input (such as Tab or Alt-F4)? – Dan Bryant Aug 19 '10 at 15:23
  • @Grzenio No I have seen suggestions like regarding this but the memory isn't significantly high. We've also been able to reproduce it on other machines. – Roo Aug 19 '10 at 15:32
  • @StevenSudit Application.Run is simply showing the application's main Form. It shouldn't be doing anything while it's idle except for standard .NET background magic. If you're suggesting what SLaks has suggested then cheers, I'll try that. – Roo Aug 19 '10 at 15:33
  • @DanBryant That's an intersting though, thanks! I'll investigate... – Roo Aug 19 '10 at 15:33
  • Sod's law is intervening right now as I can't seem to reproduce it. I'll try again tomorrow and let you know what I find. Thanks for all the help so far everyone! – Roo Aug 19 '10 at 15:34
  • @Roo: Any callbacks passed to `Control.Invoke` or `BeginInvoke` are called by `Application.Run`. They might be causing trouble. – SLaks Aug 19 '10 at 15:39
  • @Dan: Yes, the message queue pump is active, but it sounds like some of the handlers are not responding. – Steven Sudit Aug 19 '10 at 15:45
  • Your description of the hang is ambiguous. Can you please clarify? – SLaks Aug 19 '10 at 15:55
  • Thanks for your help everyone! I've posted the solution I used to resolve the issue. – Roo Aug 23 '10 at 15:38
  • @Dan: (in case anyone is wondering...) The application didn't respond to keyboard input either. – Roo Aug 23 '10 at 15:40
  • Cheers for sorting out the Hyperlinks SLaks. – Roo Aug 25 '10 at 07:04

2 Answers2

4

I would check to make sure there is no modal dialog that is being launched behind the main form. This can happen if the dialog is launched and some event causes the main form to steal back focus. You can avoid this by making sure the modal dialog has the main form as its Owner when you create it.

Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
  • Thanks Dan! Another great suggestion, I'll have a look. – Roo Aug 19 '10 at 15:36
  • In that case, the form would beep when you click it. – SLaks Aug 19 '10 at 15:45
  • 2
    @SLaks, assuming the system has sound, which is not the case for many customer machines. I've run into this particular issue before and now try to always set the Owner of any window I plan to show modally. – Dan Bryant Aug 19 '10 at 15:58
  • I modified the applciation to ensure that all Message Boxes and Modal Dialogs explicitly specified it's parent, but unfortunately this did not solve the issue despite playing a system sound when trying to click on the Form. Thanks for the suggestion though! At the very least it has cleaned up my code a bit! =) – Roo Aug 23 '10 at 15:14
3

Check where it's hanging in Application.Run; disable Just My Code in Debugger Options, then look at the call stack.

I've fixed an application that deadlocked in Application.Run because it was trying to remove an event handler from an object that a different thread was locked on. (Until the C# 4.0 compiler, event handler accessors implicitly lock(this))

However, if you're using VS2010, that isn't the exact issue.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thanks for the speedy suggestion! I'll give that a shot. – Roo Aug 19 '10 at 15:13
  • In fact, I'm actually removing and reapplying an event handler at runtime. Is this bad practice? – Roo Aug 19 '10 at 15:35
  • 1
    @Roo: No, it isn't. You just need to be aware of the multi-threading implications. If you add the handler and raise the event on different threads, use a separate variable for the null check in the raiser. – SLaks Aug 19 '10 at 15:37
  • @SLaks: That's quite right, but the worst case there would be a `NullReferenceException`, not this weird hanging. – Steven Sudit Aug 19 '10 at 15:45
  • @Steven: Yes. I was giving general advice. – SLaks Aug 19 '10 at 15:55
  • Apologies for the late reply. I thought I'd try all the solutions before responding to everyone. Thanks though SLaks, this solved my initial question of identifying where exactly the main thread is hanging. I'll update my question with details on how I solved the overal problem. – Roo Aug 23 '10 at 15:12