Article ID: 309694 - View products that this article applies to.
This article was previously published under Q309694
This problem occurs when a call is made from unmanaged code to managed code, including direct unmanaged-to-managed calls within a single DLL. For example, the problem may occur when MEC++/IJW is used in ASP.NET applications. In ASP.NET, various events can cause applications to be reloaded into a new AppDomain. If you are using MEC++ components and IJW in this application, you may receive an AppDomainUnloadException error message.
As part of the implementation of IJW, when a managed DLL that you created by using the C++ compiler loads, the runtime creates thunks for transitions from unmanaged code to managed code. These thunks contain a reference to the AppDomain in which the DLL loads. The runtime does not re-create these thunks if the DLL loads again; also, the runtime does not update the reference when the original AppDomain unloads and the DLL loads in another AppDomain.
When the program performs a transition from unmanaged code to managed code, the program uses the outdated AppDomain reference to run the managed code. Even if the original AppDomain is still loaded, the code cannot access static fields because the fields are specific to the AppDomain.
The following workarounds are grouped according to two scenarios:
Unmanaged Code to Managed Code Transition Across Two DLLsUse either of the following methods to resolve this specific problem.
Workaround 1For ASP.NET clients, allow the ASP.NET host process to shut down by trapping the DomainUnload event. However, you must first register a delegate for the DomainUnload event. To do this, follow these steps:
Workaround 2Replace all transitions from unmanaged code to managed code with calls through an unmanaged function pointer that you create by using a delegate (which is AppDomain specific). The delegate is marshaled to the unmanaged code by using Platform Invocation Services (P/Invoke) instead of IJW.
For the unmanaged DLL described in the "More Information" section of this article, the following sample code demonstrates how to use P/Invoke to use the callback method:
Unmanaged Code to Managed Code Transition in the Same DLLIn this scenario, you can have unmanaged methods (marked with #pragma unmanaged) calling methods on a managed component in the same DLL, as shown in the "More Information" section of this article. Use either of the following methods to resolve this specific issue:
Workaround 1Marshal your function pointer as a delegate and use that delegate. Because you cannot use P/Invoke on the same DLL, create a wrapper DLL that helps you to marshal a delegate to a function pointer. This exported function returns the address of the delegate that is passed to it. The following sample code is an example of this workaround:
The following sample code is for the Managed Extensions for C++ assembly that uses the previous Helper.dll:
Workaround 2Split your MEC++ assembly into two DLLs, one that contains only managed components and other that contains only unmanaged components, and then use P/Invoke as described in workaround 2 of scenario 1.
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
The problem is more prevalent if the host or client application must unload and reload AppDomains and the application contains transitions from unmanaged code to managed code that use MEC++ and IJW components. ASP.NET is one good example of such a host. In ASP.NET, the events that can trigger an AppDomain unload event can be anything from crossing a memory usage threshold to touching certain files (for example, Machine.config).
Steps to Reproduce BehaviorIn this example, you have an ASP.NET application that calls a MEC++ component, and this component has a function pointer that points to one of the methods in the MEC++ component. The component passes the function pointer to one of the following:
In the following scenarios, it is possible that, before the unmanaged function invokes the function pointer, the original AppDomain in which the DLL was loaded is unloaded. Under such conditions, the unmanaged code still references the original AppDomain and tries to call to managed code in that context.
For more information, visit the following Microsoft Developer Network (MSDN) Web sites:
Managed Extensions for C++ Programming
Creating ASP.NET Web Applications
Worker Process Isolation Mode