Сообщество программистов Autodesk в СНГ

ADN Club => Civil 3D API => Тема начата: Дмитрий Загорулькин от 29-09-2016, 13:11:18

Название: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Дмитрий Загорулькин от 29-09-2016, 13:11:18
В последнее время, при завершении отладки приложения, стала выскакивать эта ошибка:
LoaderLock was detected
Message: Попытка выполнения управляемого кода под блокировкой OS Loader. Запуск управляемого кода в пределах функции DllMain или функции инициализации образа может вызвать зависание приложения.
Что интересно, при отладке в Civil 3d 2014 такого нет (подгружаю ту же самую DLL, те же самые действия при отладке). Проявляется в версиях 2015-2017. Отладку завершаю закрытием Civil 3D. Visual Studio 2013.
Поискал в интернете, многие рекомендуют просто не обращать внимания. В принципе, на работе приложения это никак не сказывается. В настройках отладки можно отключить вывод этого сообщения. Но прежде, чем это сделать, хочу попробовать понять, в чем может быть причина. У кого-нибудь еще такое предупреждение выскакивает?
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Александр Ривилис от 29-09-2016, 13:20:40
Что интересно, при отладке в Civil 3d 2014 такого нет. Проявляется в версиях 2015-2017.
Вероятнее всего это связано с отсутствием Fiber в последних версиях. Согласен, что на это можно не обращать внимание и отключить сообщение. В действительности это не исключение. Просто "умный" отладчик анализирует код в функции DllMain, которая есть у любого exe/dll/arx/dbx/crx...-файла и которая обычно вызывается дважды - один раз при загрузке и один раз при выгрузке. Так вот если этот "умный" отладчик обнаруживает там управляемый код, то это он считает ошибкой и ругается по этому поводу.
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Александр Ривилис от 29-09-2016, 13:27:19
Кстати, в древних версиях тоже встречалось: http://forums.autodesk.com/t5/net/quot-loaderlock-has-detected-a-problem-quot-when-debugging-with/td-p/1913103
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Александр Ривилис от 29-09-2016, 13:54:10
Ну и еще одна причина: http://adndevblog.typepad.com/autocad/2012/07/loaderlock-was-detected-when-running-vlide-while-debugging-a-net-addin.html
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Дмитрий Загорулькин от 29-09-2016, 14:26:02
Ну VLIDE-то я не запускаю.
Сейчас потестировал немного. Это сообщение появляется при отладке только одного из моих проектов, и раньше его не было. Интересно, чем он отличается от остальных? Что же я такого мог добавить за последнее время, что вызвало такое поведение? Я грешу на обработчики событий приложения, коллекции документов и самих документов. Попробую разобраться.
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Александр Ривилис от 29-09-2016, 14:40:01
Ты самостоятельно не мог изменить код DllMain. И метод Terminate вызывается до кода DllMain. Но ты мог загрузить (использовать) одну из сборок, в DllMain которой используется управляемый код. Вот сюда можешь "копать" в первую очередь.
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Дмитрий Загорулькин от 30-09-2016, 04:54:58
Нашел то место в коде, которое влияет на появление этого сообщения. Это происходит, если внутри методов Overrule для метки трубы или колодца получить связанный с меткой объект через COM и затем получить его ObjectId. Вот примерно так:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.GraphicsInterface;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.Civil.DatabaseServices;
  6. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  7.  
  8. namespace CivilTest
  9. {
  10.     class PViewStructLabelDrawOverrule : DrawableOverrule
  11.     {
  12.         public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
  13.         {
  14.             StructureProfileLabel label = drawable as StructureProfileLabel;
  15.  
  16.             if (!ReferenceEquals(label, null))
  17.             {
  18.                 // Получаем COM объект метки колодца на виде профиля
  19.                 dynamic labelCOM = label.AcadObject;
  20.                 // Из свойства COM объекта метки получаем COM объект колодца на виде
  21.                 // профиля, к которому относится эта метка (через .NET не получить)
  22.                 dynamic pViewPartCOM = labelCOM.ProfileNetworkPart;
  23.                 // Получаем Id колодца на виде профиля
  24.                 ObjectId pViewPartId = AcDb.DBObject.FromAcadObject(pViewPartCOM);
  25.             }
  26.  
  27.             base.ViewportDraw(drawable, vd);
  28.         }
  29.     }
  30.  
  31.     public class PViewStructLabelDrawOverruleCmd
  32.     {
  33.         static PViewStructLabelDrawOverrule m_overrule = null;
  34.  
  35.         [CommandMethod("PViewStructLabelDrawOverruleOnOff")]
  36.         public static void CmdRun()
  37.         {
  38.             if (ReferenceEquals(m_overrule, null))
  39.             {
  40.                 m_overrule = new PViewStructLabelDrawOverrule();
  41.                 Overrule.AddOverrule
  42.                     (RXClass.GetClass(typeof(StructureProfileLabel)),
  43.                     m_overrule, false);
  44.                 Overrule.Overruling = true;
  45.             }
  46.             else
  47.             {
  48.                 Overrule.RemoveOverrule
  49.                     (RXClass.GetClass(typeof(StructureProfileLabel)),
  50.                     m_overrule);
  51.                 m_overrule = null;
  52.             }
  53.             Application.DocumentManager.
  54.                 MdiActiveDocument.Editor.Regen();
  55.         }
  56.     }
  57. }
  58.  
Строки 19, 22 и 24. Если убрать хотя бы строку 24, то сообщение уже не появляется.
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Александр Ривилис от 30-09-2016, 13:42:02
Похоже, что добавление COM/ActiveX приводит к тому, что в DllMain при выгрузке выполняется какой-то дополнительный код. Например, освобождаются ресурсы, связанные с COM-моделью AutoCAD. Возможно если их освободить раньше, такого сообщения не будет.
Название: Re: Ошибка LoaderLock was detected при отладке в Civil 3d.
Отправлено: Дмитрий Загорулькин от 30-09-2016, 14:26:12
Попробовал их освободить таким образом:
Код - C# [Выбрать]
  1.                 int lblRefCount = Marshal.ReleaseComObject(labelCOM);
  2.                 int pvPartRefCount = Marshal.ReleaseComObject(pViewPartCOM);
  3.  
  4.                 labelCOM = null;
  5.                 pViewPartCOM = null;
Но ничего не изменилось. Честно говоря, что-то иссякает мой энтузиазм по поиску и устранению причины этого поведения. Наверное, сниму я эту галочку в настройках отладки и успокоюсь :)