很抱歉这个问题比较长,但我觉得你们会发现它很有价值。在我开始之前,让我说一句,我确实尝试创建一个独立的控制台应用程序,但遗憾的是证明了不可能。这个 bug 在控制台应用程序中不会发生。在一个自包含的 ASP.NET 应用程序中也不会发生。它只会在运行在 Windows 7 上的 IIS 7.5 中发生。
错误似乎与动态语言运行时有关,因为它涉及到 __TransparentProxy
(通过 WCF)和 dynamic
变量(一个 int 的变量)的组合。产生问题的那一行是对静态方法的调用(该方法恰好不包含方法体),传入代理和动态 int。
一旦方法被调用,w3wp.exe 进程就会占用整个 CPU,并开始非常快地增加内存(对我来说大约每秒增加 100 兆字节,尽管由于垃圾回收而逐渐减少)。
为了重现此错误,请在 Visual Studio 中创建一个新的 ASP.NET 网站(“新建”|“项目”|“C#”|“Web”|“ASP.NET Web 应用程序”)。然后在 IIS 中创建一个新站点,其主目录是您的新项目(还要给“Everyone”分配完全读写权限,并确保应用程序池使用 .NET 4.0)。为新站点指定一个特定的端口,比如 7080。最后,将此代码粘贴到 Global.asax.cs 文件中:
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
dynamic dynamicId = 5;
var serviceUrl = "http://localhost:7182/FooServices.svc";
ChannelFactory factory = new ChannelFactory<IFooServices>(new WSHttpBinding(), new EndpointAddress(serviceUrl));
factory.Open();
IFooServices fooServices = ((ChannelFactory<IFooServices>)factory).CreateChannel();
BlowUpTheProgram(fooServices, dynamicId); // This line hangs
}
[ServiceContract]
public interface IFooServices
{
[OperationContract]
void Bar();
}
public static void BlowUpTheProgram(IFooServices eventServices, int authorMailboxId)
{
}
}
现在在浏览器中访问该网站,使用
http://localhost:7080
(或您选择的端口)进行访问。准备好任务管理器,因为您需要在确认了报告的症状后终止w3wp.exe进程。为了确认代理和动态是否协同工作以显示此错误,请更改此行:
dynamic dynamicId = 5;
致:
int dynamicId = 5;
重试一下,您会发现问题已经消失了并且页面已经能够加载。现在将其改回 dynamic
然后更改这一行:
IFooServices fooServices = ((ChannelFactory<IFooServices>)factory).CreateChannel();
致:
IFooServices fooServices = null;
重试一次,你会发现在这种情况下问题也已经消失了。
最后,如果我附加调试器并断点,我可以看到它在卡在这个方法调用时正在做什么。似乎总是显示如下:
mscorlib.dll!System.RuntimeMethodHandle.GetDeclaringType(System.IRuntimeMethodInfo method) + 0x2f 字节
mscorlib.dll!System.Reflection.Emit.DynamicResolver.ParentToken(int token) + 0x1f3 字节
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type delegateType, object target) + 0x29 字节
System.Core.dll!System.Linq.Expressions.Expression>.Compile() + 0xbb 字节
System.Core.dll!System.Runtime.CompilerServices.CallSiteBinder.BindCore>(System.Runtime.CompilerServices.CallSite> site, object[] args) + 0x10a 字节
System.Core.dll!System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3(System.Runtime.CompilerServices.CallSite site = {System.Runtime.CompilerServices.CallSite>}, WebApplication1.Global arg0 = {ASP.global_asax}, WebApplication1.Global.IFooServices arg1 = {System.Runtime.Remoting.Proxies.__TransparentProxy}, object arg2 = 5) + 0x3f0 字节
WebApplication1.dll!WebApplication1.Global.Application_Start(object sender = {System.Web.HttpApplicationFactory}, System.EventArgs e = {System.EventArgs}) Line 19 + 0x1b8 字节 C#
值得一提的是,我尝试在三台不同的机器上进行此操作,只能在 Windows7/IIS7.5 上复现此问题。 在 Windows Server 2008 / IIS7 上没有问题。
问题是,如何解决这个问题并成功调用该方法? 还有,为什么会发生这种情况? 我不希望在调用使用 DLR 的事物时过于小心,因为它会使 IIS 崩溃。
DontBlowUpTheProgram(fooServices, (int)dynamicId);
- Jamie Dixon