views:

114

answers:

3

One of our company's Windows Forms application had a strange problem for several month. The app worked very reliable for most of our customers but on some PC's (mostly with a wireless lan connection) the app sometimes just didn't respond anymore. (You click on the UI and windows ask you to wait or kill the app).

I wasn't able to track down the problem for a long time but now I figured out what happend. The app had this line of code

// don't blame me for this. Wasn't my code :D
Control.CheckForIllegalCrossThreadCalls = false

and used some background threads to modify the controls.

No I found a way to reproduce the application stopping responding bug on my dev machine and tracked it down to a line where I actually used Invoke() to run a task in the main thread.

Me.Invoke(MyDelegate, arg1, arg2)

Obviously there was a thread lock somewhere. After removing the

Control.CheckForIllegalCrossThreadCalls = false

statement and refactoring the whole programm to use Invoke() if modifying a control from a background thread, the problem is (hopefully) gone.

However, I am wondering if there is a way to find such bugs without debugging every line of code (Even if I break into debugger after the app stops responding I can't tell what happend last, because the IDE didn't jump to the Invoke() statement)

In other words:

If my apps hangs how can I figure out which line of code has been executed last?

Maybe even on the customers PC.

I know VS2010 offers some backwards debugging feature, maybe that would be a solution, but currently I am using VS2008.

+2  A: 

Perhaps this might help you: http://www.debuginspector.com/index.htm

It's a Visual Studio extension that allows you to track down deadlocks and it has a bunch of other nifty features for debugging threads (like viewing the callstack of multiple threads without going to the threads window).

Lirik
Looks promising, thanks.
SchlaWiener
+1  A: 

You more than likely identified the culprit correctly, setting CheckForIllegalCrossThreadCalls to false is great way to create random deadlock. The only reason the property even exists is to allow debugging borked .NET 1.x programs.

To troubleshoot deadlock, you'll need to use the Debug + Windows + Threads window to switch between the various threads and look at their call stacks. But given the likely nature of the source, that is going to be difficult since it is more than likely unmanaged code that does something with the message queue or SendMessage(). Code you didn't write and don't have source code nor debugging symbols for. They also tend to be random, the next time it deadlocks might look completely different.

Windows are fundamentally thread-unsafe objects. They have a very large amount of state associated with them. Not just in the Windows Forms class wrappers, inside Windows itself as well. I trust you fixed the problem.

Hans Passant
I just faced another deadlock with 2 thread accessing the same MySql Connection object (That's not a good idea, I know) and with Debug -> Windows -> Threads I was able to figure out what exactly happened and how to avoid it in a split second. Thanks a lot.
SchlaWiener