MissingMethodException для Func`2‹› на WinCE, хотя код, зависящий от Func`2, уже был выполнен

Я работаю над кодом C#, работающим на .NETCF 3.5 в WindowsCE 6.0, который выдает MissingMethodExceptions для Func`2‹> во время выполнения. Части кода, в которых возникает исключение, являются случайными.

Странно то, что это происходит, когда вы уже какое-то время используете приложение И где определенно многие вызовы Func`2 уже произошли. (например, через IEnumerable.Select() или .Where()). Кажется, такое поведение начинается, если вы просто загружаете достаточное количество типов в течение срока службы приложения, так что сумма размеров файлов сборки превышает ~ 18 МБ. Но на устройстве достаточно памяти (ОЗУ) для загрузки Типа.

Также активировал LoaderLogging, но безрезультатно. Он показывает мне только ошибку TypeLoad для Func`2.

Как то у меня кончились идеи: Что может быть причиной таких ошибок?

К сожалению, я не могу поделиться каким-либо кодом, потому что это 1) собственность компании, в которой я работаю, и 2) много десятков тысяч строк кода.


person cpt. jazz    schedule 30.10.2012    source источник
comment
Что ж, удачи вам в том, чтобы кто-то вам помог. Я уверен, что вы можете опубликовать пример кода, не используя ничего, что навредит компании. Компания не владеет .NET Framework.. поэтому измените некоторую жестко закодированную информацию и создайте переменную, если вам нужно показать, чего вы пытаетесь достичь   -  person MethodMan    schedule 31.10.2012
comment
DJ KRAZE, я уже писал, что проблема возникает только если загружаю много типов. Мы говорим о 20+ сборках в сочетании, которые приводят к ошибке такого типа. Вы не можете разбить это на два лайнера.   -  person cpt. jazz    schedule 31.10.2012
comment
Можете ли вы отследить или выполнить трассировку стека в строке и/или сборке, где происходит ошибка ..?   -  person MethodMan    schedule 31.10.2012
comment
Это плохо. Это происходит в случайных позициях. Единственная константа между всеми тестовыми прогонами, которые я сделал, заключалась в том, что это происходит только в том случае, если вы загружаете достаточно разных типов. Как я уже писал, это происходит, если суммы сборок составляют около 18 МБ. Последний метод в трассировке стека всегда является методом, который хочет использовать Func`2.   -  person cpt. jazz    schedule 31.10.2012
comment
Func'2 означает, что он пытается выполнить какой-то Func<,> делегат. Это одна и та же общая подпись для каждого исключения? Похоже, это может быть просто код отражения, который не может обрабатывать определенный метод.   -  person Tejs    schedule 31.10.2012
comment
да. Это всегда System.Core.Func`2. И код, где он ломается, работает для следующего запуска приложения, если только он загружается достаточно рано (имеется в виду: если я войду в окно, которое выполняет этот код до того, как будет израсходовано 18 МБ)   -  person cpt. jazz    schedule 31.10.2012
comment
Windows CE 6.0 или Windows Mobile 6? (просто для полной уверенности)   -  person Alan    schedule 31.10.2012
comment
MissingMethodException часто представляет собой замаскированную TypeLoad, и поведение, несомненно, пахнет фрагментацией, препятствующей JIT-коду. Как вы проверяете, достаточно ли памяти... для загрузки типа?   -  person ctacke    schedule 31.10.2012
comment
ctacke, я только что провел тест: у меня было ~ 28 МБ из 77 МБ ОЗУ, когда произошло исключение. Общее потребление памяти достигло пика около 10 МБ и остановилось на уровне около 7 МБ в конце. Я так понимаю проблема не в памяти?   -  person cpt. jazz    schedule 31.10.2012


Ответы (2)


Кажется, есть ограничение на .NETCF:

Можно создать только 1024 уникальных закрытых типа для одного объявления универсального типа. (Дополнительную информацию см. в разделе «Ограничения»: http://blogs.msdn.com/b/romanbat/archive/2005/01/06/348114.aspx)

Значение:

List<int> a;
List<int> b;
List<int> c;

занимает один «слот»,

List<int> d;
List<string> e;

занимает два «слота» (два уникальных замыкания) и так далее.

Сложность заключалась в следующем: обычно это вызывает ArgumentException, но иногда вместо этого .NETCF выдает MissingMethodExceptions. (см. «3. Различия в выдаваемых исключениях».): http://blogs.msdn.com/b/nazimms/archive/2005/01/25/360324.aspx)

Мы сократили использование Func`2, используя наши собственные типы делегатов, где это возможно, и это решило проблему.

person cpt. jazz    schedule 24.11.2012

вы уже сами ответили на свой вопрос, если знаете основы управления памятью Windows CE: "...так, чтобы сумма размеров файлов сборки превышала ~18 МБ. Но на устройстве достаточно памяти (ОЗУ) для загрузки Типа ...."

Вы знаете, что каждый процесс получает только 32 МБ слота памяти для программ, независимо от наличия ГБ ОЗУ или больше! То есть по дизайну. Вы знаете, что библиотеки DLL, загруженные вашим или любым другим запущенным процессом, загружаются в 32-мегабайтный слот КАЖДОГО процесса (хотя в Windows Embedded Handheld 6.5 они не загружаются в полном размере). Таким образом, чем больше загружается DLL, тем меньше доступной программной памяти у процесса. См. также http://community.intermec.com/t5/General-Development-Developer/Slaying-the-virtual-memory-monster/mp/16764 для более подробной информации.

Если память процесса, которая увеличивается с нижней части 32-мегабайтного слота, увеличивается по сравнению с загруженными DLL, которые загружаются с верхней части 32-мегабайтного слота, вы получите странное поведение программы или даже сбои.

Вышеупомянутое справедливо для всех версий ОС на базе Windows CE 5, таких как Windows Mobile 6.1, Windows Mobile 5 или даже последней версии Windows Mobile 6.5.3 (Embedded Handheld). Вышеизложенное необходимо пересмотреть для версий ОС на базе Windows CE 6.

С уважением

Йозеф

person josef    schedule 03.11.2012