2010-01-08 6 views
2

Я пишу приложение .net compact framework в C#. Он отлично работал в среде разработки, но когда он был построен в режиме выпуска и запускался сам по себе, он метал исключения MethodNotFound. Я посыпал кучу кода регистрации отладки, чтобы узнать, где он ломается, и сузил его до большой функции Init(). Это, в свою очередь, вызывает методы через несколько одноэлементных классов, которые реализуются как это:МетодNotFound, singleton класс и «оптимизировать код»

private SingletonClass() {} 

private static readonly SingletonClass _instance = new SingletonClass(); 
public static SingletonClass Instance 
{ 
get 
{ 
    return _instance; 
} 
} 

Одна вещь, которую я заметил, что запись отладки из constuctor в одноплодной классе получил бы войти перед первой записью в Init (). Похоже, что механизм выполнения выполнял что-то под капотом, прежде чем он начал запускать мой код.

Как только у меня был достаточно «отладочный» код в этих одноэлементных классах, он не будет вызывать исключение MethodNotFound, и программа будет работать нормально. Я говорю «достаточно», потому что я мог бы прокомментировать код отладки и получить MethodNotFound. Когда я снова прокомментировал это, он сработал.

Странная часть состоит в том, что когда исключение было не, то заброшенные записи журнала отладки были бы в порядке, который мой код вызывал. Это было похоже на то, что механизм времени выполнения не делал свой «под капотом» материал, который он делал при броске метода MethodNotFound.

Я попытался очистить опцию «Оптимизировать код» в проекте, который имел классы singleton, и, похоже, он решил проблему. (Сначала я попробовал это, но усвоил, что параметры проекта в проекте пользовательского интерфейса не влияют на проект бизнес-логики.)

Несколько сообщений о методе MethodNotFound, которые я нашел, говорили о недостающих DLL, неправильных версиях DLL или малое количество памяти.

Я нашел сообщение, в котором рассказывается о том, как компилятор имеет дело со статическим материалом, используемым в одноэлементных классах.

http://www.yoda.arachsys.com/csharp/singleton.html

Я думаю, что это связано с проблемой я имею, но в конце концов мне пришлось очистить «оптимизировать код», чтобы заставить его работать.

Так что мой вопрос - это то, что происходит? Он работает, поэтому на данный момент это академический вопрос. Надеюсь, это спасет кого-то еще от головной боли.

ответ

2

Вы используете отражение в любом месте своего кода, чтобы пройти стек вызовов? (поиск классов StackFrame или StackTrace)

Небольшие функции часто строятся при оптимизации кода, что означает, что определенные методы могут полностью исчезнуть из стека вызовов в сборке релиза. Если вы ожидаете, что этот метод будет присутствовать в стеке вызовов, вы можете увидеть вложение.

Когда вы добавляете код отладки в маленькую функцию, я предполагаю, что JIT перестает оценивать ее как встроенную функцию, поэтому метод возвращается в стек вызовов, и ваша проблема исчезает.

Вы можете пометить метод как непроницаемый с атрибутом CompilerServices.MethodImpl. попробуйте применить это к одной из ваших функций, которая была «исправлена» путем добавления кода отладки.

Смотрите также http://blogs.msdn.com/davidnotario/archive/2004/11/01/250398.aspx

+0

Из указанной выше ссылке: «Типичный пример действительно хорошего кандидата на встраивание является свойство getter/setter.« Я добавил [MethodImpl (MethodImplOptions.NoInlining)] к« get »операторам свойств« Instance », проверял« Оптимизировать код », и он работал. Хороший звонок! Спасибо за подсказку. – Patrick

+0

проблем нет. помог. –