Share via


AfterInvoke Must Run

During the last series of articles when I covered call context initializers I was primarily talking about what happens when things go right. Due to the nature of the task, the call context initializer extensibility point is very fragile. The thread context of a call includes sensitive information, such as caller identity, that must be correct for the call to work. Importantly as well, the thread context of a call must be cleaned up and restored for threads to be recycled for the next call. It would be very dangerous to leak information from one call to another because it's unpredictable who will get your thread next.

That's why there are strict rules about call context initializer execution and why the extensibility point is fragile. If any call context initializer gets executed through BeginInvoke, then the system will definitely call AfterInvoke before recycling the thread. If a failure occurs such that one invocation of BeginInvoke fails, then all of the call context initializers will be called with AfterInvoke even if they had never been run before. This means that your call context initializer has to be safe to call AfterInvoke without assuming that anything was initialized by BeginInvoke. Your call context initializer may be partially initialized if BeginInvoke failed with an exception, and AfterInvoke has to handle that case too.

Finally, successful completion of AfterInvoke is used as a sign that cleanup was successful. If AfterInvoke fails to complete successfully, then your process will be terminated to prevent any further damage. This is what makes the extensibility point fragile. You get penalized pretty harshly when a bug is encountered. I think that so far though not many people have tried to write call context initializers. I'm guessing that because the message left in the event log when your process is terminated by AfterInvoke is incorrect and I haven't seen anyone ask why.

Next time: Default SPN