Странная система.__ Исключение Canon

У меня есть служба Windows, которая использует одноэлементный класс ThreadQueue<T>. Когда служба запускается, он вызывает вызов ThreadQueue<string>.Start() этого класса, затем принимает и ставит задачи, ограничивающие concurrency на настраиваемое количество потоков.

ThreadQueue<string>.Start() вызывается один раз и только один раз при запуске службы.

Иногда, через несколько часов работы службы, я получаю следующее исключение:

Application: myservice.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
Stack:
   at Apollo.Business.Framework.Threading.ThreadQueue.ThreadQueue`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Start()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

Что такое System.__Canon и что делает этот вызов проходящим в нем как аргумент типа?

Может ли кто-нибудь пролить свет?

Ответ 1

Вы должны не читать что-либо в имени типа аргумента метода. System.__ Canon - это деталь реализации, связанная с тем, как генерические средства реализуются в среде CLR. Я не знаю точное использование для него, но сильно подозреваю, что он используется инструментом Ngen.exe, инструментом оптимизации в .NET, который предварительно сжимает сборки. Дженерики представляют собой проблему в пре-джиттинг, поскольку конкретный тип создается во время выполнения. Вы получите несколько копий метода, который принимает тип аргумента параметра типа. Только один метод, который обрабатывает любой ссылочный тип, дополнительные методы для каждого типа значений, если таковые имеются. System.__ Canon может быть заменяющим типом, который является владельцем места для любого ссылочного типа, позволяя Ngen.exe предиповать этот метод, даже если он не может догадаться, какой фактический тип будет использоваться во время выполнения. Что-то вроде этого.

Подходит для обуви, Apollo.Business.Framework.Threading.ThreadQueue звучит как класс, который присутствует в библиотеке стилей фреймов, которая была бы предварительно запущена, когда она будет установлена, поскольку она предназначена для использования несколькими программами.

Поэтому игнорируйте имя типа, сосредоточьтесь на фактическом исключении. Конечно, исключение NullReferenceException является очень распространенным исключением. На трассе стека ничего не видно, что даст подсказку, что ее вызывает. Я бы предположил, что проблема инициализации с этой инфраструктурой "Apollo", некоторый объект, который должен иметь значение, но по-прежнему равен нулю. Если вы заглядываете в исходный код конструктора ThreadQueue, нужно дать подсказку. Обратитесь к поставщику за помощью, если у вас его нет. Ошибка в 8-летней версии дрожания не объясняет это хорошо, эти ошибки были исправлены давным-давно.

Ответ 2

Теперь, когда среда выполнения и структура были открыты, гораздо легче ответить на этот вопрос. Определение __Canon доступно здесь. Цитата:

// Internal methodtable used to instantiate the "canonical" methodtable for generic instantiations.
// The name "__Canon" will never been seen by users but it will appear a lot in debugger stack traces
// involving generics so it is kept deliberately short as to avoid being a nuisance.

[Serializable]
[ClassInterface(ClassInterfaceType.AutoDual)]
[System.Runtime.InteropServices.ComVisible(true)]
internal class __Canon
{
}

Как поясняется в комментарии, это деталь реализации для генериков и является аббревиатурой для "канонического".