If you can run long runs locally, just go to the Debug menu and select "Break all". Then you can use the Debug -> Windows -> Threads view to view all of your active threads. You can probably determine what takes so long.
Alternatively, you can set Debug = false; then attach Visual Studio to your process and set it to break down into the ThreadAbortExceptions instances that have been selected.
Alternatively, you can set DebugDiag to capture the dump file when a long execution is detected. You can use WinDbg (hard) or Visual Studio 2010 and higher to load these dump files and verify the health of your program.
Finally, you can try to reflect the behavior of the RequestTimeoutManager class, which periodically calls TimeoutIfNeeded (DateTime now). However, I cannot trivially see a way to change this to use the debug = false behavior.
source share