Вроде поправил.Да. С форматированием теперь всё нормально. Теперь пара вопросов:
Может это связано как-то с размером файла? У меня файл получается больше 10мб?Это вряд-ли связано с файлом-источник. Если вы при отлове ошибки написали "Файл испорчен", то это еще не истина )
Может это связано как-то с размером файла? У меня файл получается больше 10мб?Нет. Если ты вручную средствами AutoCAD можешь вставить этот блок, то и через API это должно работать.
Если вы при отлове ошибки написали "Файл испорчен", то это еще не истина )100%. Поэтому я и предложил убрать TRY/CATCH.
2) Поэкспериментируй с заменой DuplicateRecordCloning.Ignore на DuplicateRecordCloning.ReplaceИ это в первую очередь пробуй
не обращайте внимание, она для пользователей.Я и не обращаю внимания, но она мне мешает увидеть трассировку и код ошибки.
в Sb.Plugin.InsertBlockFromDataBaseJig.BlockJigCmd(SpecifficationDataObject BlockData, Form _Form)
в Sb.Plugin.InsertBlkRefFromDataBase.ButtonInsertBlock_Click(Object sender, EventArgs e)
Еще entityJig используется, но до него не успевает доходитьЭммммм... А ошибка вроде гласит об обратном)
Хотя опять же у меня на компе все работает без ошибок.1) Чертеж один и тот же на обоих PC?
1) Поменяй SourceDb.WblockCloneObjects на ActiveDb.WblockCloneObjectsЕсли это не поможет - делай простейшую тестовую команду на основе этого: http://adndevblog.typepad.com/autocad/2012/05/insert-block-from-a-different-dwg-using-net-.html
2) Поэкспериментируй с заменой DuplicateRecordCloning.Ignore на DuplicateRecordCloning.Replace
3) Поставь блокировку doc перед WblockCloneObjects4) убери TRY/CATCH, чтобы увидеть системную ошибку.(сделано)
Александр, а можно для понимания пояснить 1), 2). Т.к. опять же на моем компе работает и так и так.1) Этот метод следует использовать с той базой, над которой будет выполняться модификация
Вообщем выяснилось следующее убрал файл с блоками с виртуального диска на локальный и все заработало как часы.Возможно это проблема виртуального диска, хотя...
Еще вопрос по поводу к какой базе все-таки применять метод WblockCloneObjects.Теоретически должно работать и так, и так. Но так как копируется не только сама запись таблицы блоков, но и все связанные с ней объекты, правильнее указывать ту базу, в которую будет производится копирование. Я сталкивался с ошибками, которые возникали из-за неправильного указания базы.
Вообщем выяснилось следующее убрал файл с блоками с виртуального диска (который создается командой subst) на локальный и все заработало как часы.SourceDb.ReadDwgFile не загружает файл в память. А делает отложенную загрузку по требованию.
Все-таки где-то сидит косяк. После вставки сотни блоков вылезла такая же ошибка. Но похоже ошибка все-таки где-то нижеReadDwgFile обращается к RealDwg, который является потоко не безопасным, а ты вызываешь его 100 раз. Постарайся минимизировать количество вызовов ReadDwgFile в коде, например подгрузить все нужные блоки сразу в чертеж, а не по мере необходимости.
Самое плохое в том, что на моем компе не удается никак отловить ни в релизной сборке, ни в другой.можно добавить Dispose() после использования объектов везде, где можно, кроме редактора и документа.
Dispose новой базы засунул в событие CloseЕсли создание базы была в Using, то никакой Close не нужен. Более того он вреден.
Но стало иногда ловится EWrongDataBase.Из документации: eWrongDatabase -- if the owners are not from the same database в WblockCloneObjects. Т.е. как раз возможен случай, когда этот метод вызывается для неправильной базы.
Засунул Readdwgfile в событие Load формы. Dispose новой базы засунул в событие Close. Стало гораздо стабильнее. Но стало иногда ловится EWrongDataBase.не стоит не то и не туда засовывать. Сперва, как предложил Александр, создай тест, где будет выполняться загрузка без всяких форм.
Если это не поможет - делай простейшую тестовую команду на основе этого: http://adndevblog.typepad.com/autocad/2012/05/insert-block-from-a-different-dwg-using-net-.html
Явно укажи в ней имя файла и имя блока. Проверь её работоспособность. Не забывай передавать dll-файл в конфигурации Release.
При таком варианте ощутимо быстрее, т.к. один раз вызывается readdwgfile, а на его вызов тратится существенное время.Это правда. Но это если блоки у тебя хранятся в одном файле и ты до закрытия формы занимаешься их вставкой.
Если у Вас есть возможность проверьте плиз код в 39 посте на файле с блоками при которых рушится автокад (файл в том же посте приложен)?Я проверил твой вариант (VB - Release) в чистом AutoCAD 2012 (2011 версии у меня нет) - всё сработало нормально.
2. Попробуй убрать строки:Хотел уточнить в каком случае тогда нужно переключать? Я предполагал если код работает с такой-то базой, то я делаю ее текущей, конечно в случае если идет работа с несколькими базами.
HostApplicationServices.WorkingDatabase = SourceDb;
HostApplicationServices.WorkingDatabase = ActiveDb;
Для цели вставки блоков, переключать не нужно.
Добавил mapping.DisposeНа это и подозревал.
Хотел уточнить в каком случае тогда нужно переключать? Я предполагал если код работает с такой-то базой, то я делаю ее текущей, конечно в случае если идет работа с несколькими базами.В большинстве сценариев работы это не требуется, просто взяли объект, скопировали и все.
DirectCast(SourceDb.BlockTableId.Open(OpenMode.ForRead), BlockTable)Александр метод Open помечается как устаревший (For advanced use only. Use GetObject instead). Это не приведет к каким-нибудь сюрпризам?
Нет. Никаких сюрпризов не будет. И будет работать быстрее. Но его очень желательно использовать в блоке Using, а если нет, то не забывать принудительно вызывать его метод Close. Иначе развалишь AutoCAD. Не зря написано: For advanced use onlyDirectCast(SourceDb.BlockTableId.Open(OpenMode.ForRead), BlockTable)Александр метод Open помечается как устаревший (For advanced use only. Use GetObject instead). Это не приведет к каким-нибудь сюрпризам?
5. Предложение Дмитрия №4. Добавил mapping.Dispose после WblockCloneObjects. Пока вылечило. Ошибка не воспроизводится. На AutoCal MEP 2012 х64 под Win8 и на Autocad MEP 2011 х64 под Win7 64.Похоже на элементарную утечку памяти. Но у меня она не воспроизвелась - возможно памяти было достаточно, возможно причина в том, что у меня чистый AutoCAD, а не MEP. Может быть если зациклить твой код для вставки тысячи блоков это бы воспроизвелось. В действительности при WblockCloneObjects mapping заполняется часто достаточно большим количеством ObjectId объектов (в твоём случае это как минимум ObjectId всех элементы блоков, слоёв, типов линий, динамическими вещами и т.д.). Ну и если это делается многократно, то утечка будет. Короче говоря Привалов Дмитрий абсолютно прав, что всё, что создал нужно чистить после того как ни ты ни AutoCAD это уже не использует. Можно было при помощи блока Using.
Переключать нужно тогда, когда AutoCAD сам не знает откуда ему брать ссылки на объекты. Например, для примитива DBText где взять ObjectId для текстового стиля по-умолчанию, или ObjectId для слоя. По поводу:2. Попробуй убрать строки:Хотел уточнить в каком случае тогда нужно переключать? Я предполагал если код работает с такой-то базой, то я делаю ее текущей, конечно в случае если идет работа с несколькими базами.
HostApplicationServices.WorkingDatabase = SourceDb;
HostApplicationServices.WorkingDatabase = ActiveDb;
Для цели вставки блоков, переключать не нужно.
SelectCrossingPolygonэто отношения к делу не имеет, т.к. тут важно не WorkingDatabase, а ActiveDocument.
Похоже на элементарную утечку памяти. Но у меня она не воспроизвелась - возможно памяти было достаточно, возможно причина в том, что у меня чистый AutoCAD, а не MEP.
Отправлю инфу в личку, т.к. ее много, она не оформлена и явно не для этой темы.Создавай тему - обсудим. В данном случае - это явная утечка памяти, т.к. mapping - это обертка для коллекция пар объектов, для которой Dispose вызывает освобождение памяти коллекции. От потока это не зависит.