Ошибка в динамическом языке во время выполнения в сочетании с IIS 7.5
Я прошу прощения за этот вопрос, но я думаю, что вы все найдете это стоит. Прежде чем я начну, позвольте мне сказать, что я действительно пытался создать изолированное консольное приложение, но, к сожалению, это оказалось невозможным. Ошибка не возникает в консольном приложении. Это не происходит в автономном приложении ASP.NET. Это происходит только при запуске в IIS 7.5 в Windows 7.
Кажется, ошибка связана с динамической средой исполнения языка, поскольку включает в себя комбинацию __TransparentProxy
(через WCF) и dynamic
переменная (целое число). Строка, вызывающая проблему, - это вызов статического метода (который, как оказалось, не содержит тела метода), передающего как прокси, так и динамический int.
Как только метод вызван, процесс w3wp.exe занимает весь ЦП и начинает очень быстро увеличивать объем памяти (для меня около 100 мегабайт в секунду, хотя он, вероятно, уменьшается из-за GC'ing).
Чтобы воспроизвести эту ошибку, создайте новый веб-сайт ASP.NET в Visual Studio ("Новый" | "Проект", "C#" | "Веб" | "Веб-приложение ASP.NET"). Затем создайте новый сайт в IIS, домашний каталог которого является вашим новым проектом. (также предоставьте "Все" полный доступ на чтение / запись к этой папке и убедитесь, что пул приложений использует.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) + 0x2f байт
mscorlib.dll!System.Reflection.Emit.DynamicResolver.ParentToken(int token) + 0x1f3 байта
[Родной для управляемого перехода]
[Управляемый к Родному Переходу]
mscorlib.dll! System.Reflection.Emit.DynamicMethod.CreateDelegate (System.Type DelegateType, цель объекта) + 0x29 байт.
System.Core.dll!System.Linq.Expressions.Expression>.Compile() + 0xbb байт
System.Core.dll!System.Runtime.CompilerServices.CallSiteBinder.BindCore>(System.Runtime.CompilerServices.CallSite> сайт, объект [] args) + 0x10a байт
System.Core.dll!System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3(System.Runtime.CompilerServices.CallSite site = {System.Runtime.CompilerServices.CallSite>}, WebApplication1.Global arg0 = {ASP.global_asax}, WebApplication arg1 = {System.Runtime.Remoting.Proxies.__TransparentProxy}, объект arg2 = 5) + 0x3f0 байт
WebApplication1.dll!WebApplication1.Global.Application_Start(отправитель объекта = {System.Web.HttpApplicationFactory}, System.EventArgs e = {System.EventArgs}) Строка 19 + 0x1b8 байт C#
Для справки, я попробовал это на трех разных машинах и смог воспроизвести только на коробках Windows7/IIS7.5. На коробке Windows Server 2008 / IIS7 проблем не было.
Вопрос в том, как мне решить эту проблему и успешно вызвать метод? Кроме того, почему это происходит? Я не хотел бы быть слишком осторожным при вызове вещей, которые будут использовать DLR, потому что это приведет к краху IIS.
1 ответ
Я не могу ответить, почему это происходит, однако dynamic
Возражать int
при передаче параметр будет работать.
DontBlowUpTheProgram(fooServices, (int)dynamicId);
Возможно, кто-то с большим знанием внутренних органов придет с более полным объяснением.