views:

338

answers:

1

Is there a way for me to hook the exit of managed threads (i.e. run some code on a thread, just before it exits?)

I've developed a mechanism for hooking thread exit that works for some threads. Step 1: develop a 'hook' STA COM class that takes a callback function and calls it in its destructor. Step 2: create a ThreadStatic instance of this object on the thread I want to hook, and pass the object a managed delegate converted to an unmanaged function pointer. The delegate then gets called on thread exit (since the CLR calls IUnknown::Release on all STA COM RCWs as part of thread exit).

This mechanism works on, for example, worker threads that I create in code using the Thread class.

However, it doesn't seem to work for the application's main thread (be it a console or windows app). The 'hook' COM object seems to be deleted too late in the shutdown process and the attempt to call the delegate fails.

(The reason I want to implement this facility is so I can run some native COM code on the exiting thread that works with STA COM objects that were created on the thread, before it's 'too late' (i.e. before the thread has exited, and it's no longer possible to work with STA COM objects on that thread.))

A: 

Do you control thread creation? It's probably simplest to simply wrap the thread's code in a try...finally clause, and put your code in the finally.

Note that when the AppDomain shuts down, you can never be sure that your code will be called since the shutdown may be less than graceful.

When you say "Destructor" I presume you mean a C++/CLI destructor - i.e. the .Dispose() method?

If you need to support hooking before the process exits, you could try the AppDomain.CurrentDomain.ProcessExit event - which doesn't seem to fire on an unhandled exception, or AppDomain.CurrentDomain.UnhandledException which seems to fire only on an unhandled exception.

None of this looks particularly robust, mind you...

Eamon Nerbonne
Paragraph 1: nope. Paragraph 2: yes, but no problem. Paragraph 3: no, the destructor of the native C++ implemented coclass. Paragraph 4: hmmm, I'll check that out. Paragraph 5: necessary nonetheless.
mackenir
Unfortunately, AppDomain ProcessExit gets called on a different thread from the main thread.
mackenir