Извършване на многопоточни задачи в приставката AutoCAD .Net

Наясно съм, че API на Autocad не трябва да се извикват/използват в многопоточност. Но какво ще кажете за извършване на многонишкова работа (в Autocad .Net плъгин), която не включва никакви специфични извиквания/типове на Autocad?

Ситуацията е следната: 1. някои CAD полилинии се извличат чрез API, техните свойства, които представляват интерес, се обвиват в потребителски типове и след това 2. В друг слой се правят някои многонишкови изчисления спрямо тези потребителски типове. 3. Приложението персонализира типовете, които записват своите резултати обратно в полилиниите на CAD чрез API на Autocad.

Само втора стъпка се извършва в много нишки.

Приложението използва метода StartTransaction(), за да получи обекта Transaction. Досега не съм имал сривове от много години. Но сега се опитвам да използвам StratOpenCloseTransasction() и се срива много пъти. Специално се срива, когато се извика Editor.Rengen(), тъй като мисля, че преминава през всеки обект в базата данни и може би някои са повредени. Наистина стесних проблема и една от причините очевидно е тази многонишковост.

Има ли някаква причина CAD да се срива при извикване на много нишки, въпреки че не са ангажирани API? Безопасно ли е да използвам многопоточност по този начин? StartTransaction() обработва ли обекти по-добре от StartOpenCloseTransaction по отношение на изхвърлянето им? Тъй като не съм имал сривове при това.

Много благодаря


person ali    schedule 29.08.2015    source източник
comment
Току-що получих някои грешки на Editor.Regen. Това се дължи на преходни образувания.   -  person Maxence    schedule 02.09.2015
comment
Какво имаш предвид под преходни обекти, Максенс?   -  person ali    schedule 03.09.2015
comment
Преходните обекти са временни обекти (които не са свързани с база данни), изчертани с класа TransientManager. Пример за този вид обекти е изгледният куб. По време на реген тези обекти се обновяват. TransientManager може да работи само с активния документ. Може би с вашата фонова обработка AutoCAD е объркан относно активния документ.   -  person Maxence    schedule 03.09.2015
comment
@Maxence Много благодаря за подсказката. Не използвам преходни обекти. Не можах/не стигнах до дъното в края и го промених на метод StartTransaction, както и вие предложихте. По някаква причина използването на метода StartOpenCloseTransaction за вмъкване на обекти е повредило цветовете им на чертежа, сякаш вече не са валидни обекти. Мисля, че затова Реген правеше изключение. Никога не съм изпитвал това със StartTransaction от години.   -  person ali    schedule 04.09.2015


Отговори (2)


Голямото предизвикателство при многонишковостта е да се синхронизира обратно с основната нишка (нишка на AutoCAD). Разбира се, ако приемем, че не предавате AutoCAD тип/данни/обект на друга нишка (само чисти .NET/C++ данни).

Като сте наясно с рисковете, можете да синхронизирате обратно с подхода, описан в този PDF: http://aucache.autodesk.com/au2011/sessions/2526/class_handouts/v1_CP2526_Taget.pdf

Ето основната част от кода за проверка дали AutoCAD може да получава външни повиквания:

bool isQuiescent(AcApDocument* pDoc = curDoc())
{
return ( (pDoc != NULL)
 && pDoc->isQuiescent()
 && ((pDoc->lockMode() == AcAp::kNotLocked) ||
 (pDoc->lockMode() == AcAp::kNone))
 && (acedCommandActive() == 0) // no script or lisp is active
 && (acDocManager != NULL)
 && (acDocManager->inputPending(pDoc) == 0)
 && (::GetInputState() == 0)
 );
}
person Augusto Goncalves    schedule 29.08.2015
comment
Този примерен код в този документ не е реалистичен. Не виждам потребител да стартира команда, след което да продължи да работи, докато обработката се извършва във фонов режим и изведнъж да видя обекти да се появяват в неговия чертеж! Това, което правя в тази ситуация, е да покажа известие, след което да обработя резултата от изчислението, когато потребителят щракне върху връзка в балончето за известия. Команда IMPORTIGES работи така. - person Maxence; 29.08.2015
comment
Благодаря за линка. Знаете ли дали тази част от кода и регистрирането/обработването на съобщението в прозореца трябва да бъде в C++ и след това да бъде извикано в c#? Или можем просто да направим горната проверка на c# и ако е вярно, тогава да заключим, че е безопасно да извикаме CAD API в главната нишка. - person ali; 29.08.2015
comment
този код трябва да ви каже кога AutoCAD е готов да получава обратни повиквания. връзката PDF трябва да има повече подробности. - person Augusto Goncalves; 31.08.2015
comment
В управлявания API на AutoCAD има свойство Application.IsQuiescent. Не съм сигурен, че е еквивалентен на този C++ код. Има и свойството Editor.IsQuiescent. - person Maxence; 01.09.2015

Защо използвате StartOpenCloseTransaction? Има малко увеличение на производителността, но стандартните транзакции са по-безопасни. Проблемът с OpenCloseTransaction е, че никой не знае как точно работи. Единствената документация е:

се държи подобно на обект Transaction, който обвива методите Open и Close на обект, което улеснява затварянето на всички отворени обекти, вместо да се налага изрично затваряне на всеки отворен обект. Препоръчва се за използване в функции за поддръжка или помощни програми, които могат да бъдат извикани неизвестен брой пъти, и се използва при работа с повечето манипулатори на събития.

което не е много ясно...

Използвам го само в манипулатори на събития, където обектите са в поток, когато трябва да започна транзакция.

person Maxence    schedule 29.08.2015
comment
Благодаря за вашият отговор. Въпросът, публикуван в връзката по-долу, е защо използвах StartOpenCloseTransaction. - person ali; 29.08.2015
comment
forums.autodesk.com/ t5/net/ - person ali; 29.08.2015
comment
Ако сте извън процеса, маршалингът на вашите извиквания от вашето приложение към AutoCAD ще забави приложението ви повече, отколкото използването на няколко транзакции. Това, от което се нуждаете, е набит интерфейс. - person Maxence; 29.08.2015
comment
Ами използвах StartTransaction по тромав начин: предаване на всички обекти и извършване на транзакцията наведнъж (ако това означава). - person ali; 29.08.2015
comment
Когато казвате, че стандартните транзакции са по-безопасни (с което, предполагам, имате предвид метода StartTransaction()), има ли доказателства/доказателство/причина за това? - person ali; 29.08.2015
comment
Най-малко две: транзакциите OpenClose не могат да бъдат вложени и не могат да бъдат достъпни чрез Database.TransactionManager.TopTransaction (не можете също да използвате ObjectId.GetObject, което е удобен начин за отваряне на обект). Вместо безопасно, трябваше да използвам думата удобно. - person Maxence; 29.08.2015