Execute code when VisualStudio debugger is exiting
Asked Answered
I

2

16

I had assumed that when terminating debugging (such as by hitting the Stop button, or hitting Shift+F5), that any class implementing a finalizer or IDisposable would be, well, disposed.

I have some classes that implement IDisposable. There are a few things I'd like to (try) and do as the application exits from the debugger (or from crashing in production). Right now, Dispose() does not appear to be called, nor a finalizer ~MyClass(){}

Is there a way to do this?

Ilka answered 13/7, 2012 at 21:15 Comment(10)
Unless the crash is caused by a trappable exception, there's no guarantee of ANY code running post-crash. that's the nature of an application crash. Something went wrong and now your process has been forcibly terminated.Fanning
@Boo Understood. But, if I can run the code under at least a subset of the scenarios, I'll take that.Ilka
Hitting the stop button in the debugger is the same as the OS terminating your app. It's unceremonious and pretty darn sudden, without regard for whatever the application might current be doing or intending to do.Fanning
How about just terminating the application in a non-violent manner? Like the close button on the main window?Fanning
@Boo this is a Windows Service that, while debugging, runs as a basic program with an un-ending while(true){ Thread.Sleep(1000); } in the primary thread.Ilka
@Boo I suppose that is an argument for making my windows-service debugger a basic windows form I can close, isntead of a never ending while loopIlka
the service class should have a Stop or Shutdown method you can callFanning
@Boo thanks, that makes another argument for creating a form window while in debug mode (so I can call stop)Ilka
Use Ctrl+C to terminate and make sure you have a handler for Console.CancelKeyPress to perform the Stop or Shutdown.Manilla
Is there still no workaround?Wilhelm
G
2

For normal stopping of Windows services, you should put your code in your Stop method.

http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.stop.aspx

In general, rude thread aborts and rude app domain unloads aren't going to run 'normal' finalizers - you can get more details in this MSDN article.

https://web-beta.archive.org/web/20150423173148/https://msdn.microsoft.com/en-us/magazine/cc163716.aspx

Up to this point, I've simply talked about thread aborts as the result of the runtime throwing ThreadAbortException on a thread. Typically, this will cause the thread to terminate. However, a thread can handle a thread abort, preventing it from terminating the thread. To account for this, the runtime provides a more powerful action, the aptly named rude thread abort. A rude thread abort causes a thread to cease execution. When this happens, the CLR makes no guarantees that any back-out code on the thread will run (unless the code is executing in a CER). Rude, indeed.

Similarly, while a typical application domain unload will gracefully abort all threads in the domain, a rude application domain unload will rudely abort all threads in the domain, and makes no guarantees that normal finalizers associated with objects in that domain will run. SQL Server 2005 is one CLR host that makes use of rude thread aborts and rude application domain unloads as part of its escalation policy. When an asynchronous exception occurs, the resource allocation failure will be upgraded to a thread abort. And when a thread abort occurs, if it doesn't finish within a time span set by SQL Server, it'll be upgraded to a rude thread abort. Similarly, if an application domain unload operation does not finish within a time span set by SQL Server, it'll be upgraded to a rude application domain unload. (Note that the policies just laid out are not exactly what SQL Server uses, as SQL Server also takes into account whether code is executing in critical regions, but more on that topic shortly).

Grebe answered 13/7, 2012 at 23:2 Comment(0)
T
1

Well, the CLR doesn't make any promises regarding when your objects are going to be collected or disposed-of.

You can try calling the garbage collector explicitly, but I don't think that's a recommended approach.

The best thing to do is use your IDisposable objects inside a using block.
That's the only time when you're guaranteed when they'll be disposed of.

Tapster answered 13/7, 2012 at 21:19 Comment(2)
FWIW, 'using' is just syntax sugar for a try/finally, so it's no more guaranteed than a regular finally block.Grebe
yes, it's syntactic sugar for try/finally(Dispose()). see here- "The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block". msdn.microsoft.com/en-us/library/yh598w02%28v=vs.100%29.aspxTapster

© 2022 - 2024 — McMap. All rights reserved.