2012-03-16 3 views
1

В моем приложении WPF при первом открытии меню происходит пауза, вызванная ленивой загрузкой Accessibility.dll.Медленная ленивая загрузка Accessibility.dll?

Как вы можете себе представить, это очень раздражает, поэтому я хотел бы нагрузить эту сборку при запуске. Я попробовал несколько способов сделать это без везения. например, с помощью Assembly.Load() или AppDomain.Load(). Ни один из этих вызовов не приводит к загрузке сборки (т. Е. Я не получаю событие AssemblyLoaded. Я попытался прямо ссылаться на assmebly, чтобы получить правильное AssemblyName для вызова этих методов, но все равно не повезло.

Каков правильный способ ? это произошло

Большое спасибо Dan

Edit: Call Stack сборочного нагрузки (после нажатия меню)

mscorlib.dll System.AppDomain.OnAssemblyLoadEvent (System.Reflection.RuntimeAssemblyLoadedAssemly [! Родной ! Managed Переход]
[Успели Native Перехода]
PresentationFramework.dll System.Windows.Controls.Primitives.Popup.CreateWindow (BOOL asyncCall)

Звонок из всплывающего окна:

_secHelper.ForceMsaaToUiaBridge (_popupRoot.Value);

ответ

2

Да, вы можете использовать отражение (RuntimeHelpers.PrepareMethod), чтобы заставить компилятор JIT скомпилировать методы, которые вы хотите, в фоновом потоке. Вот CodeProject article, который описывает это.

RuntimeHelpers.PrepareMethod является потокобезопасным, поэтому его можно использовать в этом сценарии.

Это код, слегка изменен, чтобы исключить общие и P/Вызывается функции:

Thread jitter = new Thread(() => 
{ 
    var flags = BindingFlags.DeclaredOnly | BindingFlags.NonPublic | 
       BindingFlags.Public | BindingFlags.Instance | 
       BindingFlags.Static; 

    foreach (var assembly in AssembliesToPreload) 
     foreach (var type in a.GetTypes()) 
      foreach (var method in type.GetMethods(flags)) 
      { 
       if (method.ContainsGenericParameters || 
        method.IsGenericMethod || 
        method.IsGenericMethodDefinition) 
        continue; 

       if ((method.Attributes & MethodAttributes.PinvokeImpl) > 0) 
        continue; 

       RuntimeHelpers.PrepareMethod(method.MethodHandle); 
      } 
    } 
}); 

jitter.Priority = ThreadPriority.Lowest; 
jitter.Start(); 
+0

Сборка фреймов предварительно задана ngen.exe –

+0

Кажется, что Accessibility.dll просто содержит несколько интерфейсов, поэтому не уверен, могу ли я применить эту технику. Я добавил стек вызовов выше, когда сборка сначала загружается при открытии меню. –

+0

@ HansPassant: вы правы, я не понимал, что это была сборка фреймов. Хотя я до сих пор не использовал его, если я правильно понял, это COM-оболочка, поэтому узким местом может быть создание COM-объекта? Если он предполагается использовать в модели STA, OP все равно придется создавать экземпляр в потоке графического интерфейса, поэтому фоновый init не поможет. – Groo

0

Я предполагаю, что есть тип в вашем Accessibility.dll, что вы хотите, например, или использования.

Я думаю, что здесь требуется время JIT, поэтому заставить JIT запускать только создать/использовать экземпляр вашего объекта. Я склонен добавлять такие методы, как Accessibility.RunJIT(), когда я в аналогичной ситуации. То, что я делаю, это просто создать экземпляр класса.

Вы также можете посмотреть на NGen. http://msdn.microsoft.com/en-us/library/6t9t5wcf(v=vs.110).aspx

+0

Извините, что в моем вопросе неясно, я ссылался на сборку рамки Accessibility.dll. –

Смежные вопросы