Тема: Фоновая обработка чертежа

Возникла необходимость создания подобия фоновой обработки чертежа. Идеальный вариант - отдельный поток, который имеет доступ к базе Автокада (подозреваю, что это не реально). Может кто-то уже решал подобную задачу и может поделится опытом?

Re: Фоновая обработка чертежа

Очень не хотел отвечать в эту тему - думал, что кто-то реально это использует и поделится информацией. Но так как добровольцев не нашлось...

bool Flag_Thread_Start = false;
// Добавление примитива в базу чертежа - стандартная функция
Acad::ErrorStatus postToDb(AcDbDatabase *pDb, AcDbEntity* ent, AcDbObjectId& objId)
{
    Acad::ErrorStatus      es;
    AcDbBlockTable*        pBlockTable;
    AcDbBlockTableRecord*  pSpaceRecord;
    if ((es = pDb->getSymbolTable(pBlockTable, AcDb::kForRead)) != Acad::eOk) {
        return es;
    }
    if ((es = pBlockTable->getAt(ACDB_MODEL_SPACE,
                                 pSpaceRecord,
                                 AcDb::kForWrite)) != Acad::eOk) {
        return es;
    }
    if ((es = pBlockTable->close()) != Acad::eOk) {
        return es;
    }
    if ((es = pSpaceRecord->appendAcDbEntity(objId, ent)) != Acad::eOk) {
        return es;
    }
    if ((es = pSpaceRecord->close()) != Acad::eOk) {
        return es;
    }
    return ent->close();
}
// Фоновая задача
void OtherThread(void *parm)
{
  AcApDocument *cDoc = curDoc();
  if (cDoc) {
    int iColor = 1;
    AcDbDatabase *pDb = cDoc->database();
    AcDbObjectId eId;
    Acad::ErrorStatus es;
    if (pDb) {
     es = acDocManager->lockDocument(cDoc);
     if (es == Acad::eOk) {
        AcDbLine *pLine = new AcDbLine(AcGePoint3d(0,0,0),AcGePoint3d(10,10,0));
        pLine->setColorIndex(iColor);
        postToDb(pDb,pLine,eId);
        acDocManager->unlockDocument(cDoc);
        while (Flag_Thread_Start) {
          es = acDocManager->lockDocument(cDoc);
          if (es == Acad::eOk) {
            AcDbObjectPointer<AcDbLine>pLine(eId,AcDb::kForWrite);
            if (pLine.openStatus() == Acad::eOk) {
              pLine->setColorIndex(++iColor%256);
            }
            acDocManager->unlockDocument(cDoc);
          }
          Sleep(300);
        }
     }
    }
  }
  _endthread();
}
// - MultiThread.Thread command (do not rename) - Обработчик команды
static void MultiThreadThread(void)
{
    // Add your code for command MultiThread.Thread here
    if (!Flag_Thread_Start) {
      Flag_Thread_Start = true;
      _beginthread(&OtherThread,0,NULL);
    }
}

Конечно можно нарваться на неприятности, т.к. Autodesk специально пишет, что делать этого не следует, но если очень осторожненько, проверяя, что AcDbDatabase существует и не закрыта, AcApDocument "живой" и т.д., то можно попробовать. Безусловно это только IMHO, но с данным примером я поигрался и он работает. Более того, когда для отрезка выбираешь Properties, то номер цвета мелькает в окошке. smile

Re: Фоновая обработка чертежа

Упс! Последнюю функцию нужно читать так.

static void MultiThreadThread(void)
{
    // Add your code for command MultiThread.Thread here
    if (!Flag_Thread_Start) {
      Flag_Thread_Start = true;
      _beginthread(&OtherThread,0,NULL);
    } else
      Flag_Thread_Start = false;
}

Тогда повторный запуск остановит отдельную задачу.
Ну и не забыть завершить задачу при выгрузке приложения, закрытии чертежа и т.д.

Re: Фоновая обработка чертежа

> Александр Ривилис
Забавный пример, но честно сказать, страшновато smile
Дело в том, что передо мной стоит весьма серьёзная задача, придётся написать много кода, не хотелось бы выяснить, что ничего невыйдет спустя несколько недель после начала работы...
Хотя... Ключевой вопрос, достаточно ли простого блокирования документа для корректной работы? Если lockDocument поддерживает многопоточность (это вполне возможно), то проблем нет, а иначе... Думаю, что погоняю приведённый пример в течении нескольких дней на нескольких машинах и посмотрю что выйдет.
Впрочем, у меня уже два варианта. Первое, что мне пришло в голову, это из одельного потока периодически посылать строку на выполнение (sendStringToExecute), которая бы вызывала "фоновый" обработчик.

Re: Фоновая обработка чертежа

> archimag
В этом примере как минимум не хватает обработки того факта, что документа уже нет (закрыли его или AutoCAD) - при выходе из AutoCAD точно будет вылет. Я тут вот о чем подумал. Все немодальные диалоги ведь тоже выполняются фактически асинхронно с основным процессом. Для них в рекомендациях Autodesk только lock/unlock. Так что в принципе должно работать. Еще одно замечание. Когда забыл поставить проверку if (pLine.openStatus() == Acad::eOk) { при попытке получения свойств отрезка развалил AutoCAD. Так что тут очень осторожно... По поводу sendStringToExecute - она будет выполняться только когда AutoCAD простаивает, или может нарушить выполнение текущей команды AutoCAD - не советую. Если уж фоновый процесс должен выполняться во время простоя, то лучше проверять состояние AutoCAD на предмет простоя и только в это время разрешать работать отдельной задаче, реализуя для нее что-то типа Suspend/Resume. Это Windows API позволяет.
Еще один вариант - использовать SetTimer(), т.е. фоновый процесс будет работать в его обработчике - это у меня точно где-то используется и проблем не вызывало. Разве что может притормаживать...

Re: Фоновая обработка чертежа

Упс! Запуск sendStringToExecute из отдельного потока может (читай - должен) развалить AutoCAD - поверь на слово. Если уж использовать что-то аналогичное, то acedPostCommand() - это безопасно, но можно послать только в активный документ, и будет видна строка запуска... :(

Re: Фоновая обработка чертежа

> Александр Ривилис
Почему sendStringToExecute из отдельного потока должен развалить Автокад? Я посылаю строку на выполнение из немодального окна и почти всегда она проходит, когда не проходит - перехватываю ошибку и повторяю операцию немного позже. Ведь тоже самое можно сделать с помощью COM вообще из другого процесса. Мне как раз и надо, что бы обработка проводилась во время простоя - иначе буду мешать пользователю.

Re: Фоновая обработка чертежа

> archimag
Я же попросил поверить на слово. :-; Если хочешь подробнее - напиши на e-mail или в ICQ.

Re: Фоновая обработка чертежа

> Александр Ривилис
На слово верить не привык smile На следующией неделе попробую ручками пощупать...

Re: Фоновая обработка чертежа

> archimag
Как знаешь. Информация из первоисточника...

Re: Фоновая обработка чертежа

Не сочтите некропостером  :D

У класса AcApDocManager имеется экземплярный метод

    virtual void executeInApplicationContext(void (*procAddr)(void *), void * pData) const = 0;

Правильно ли я понимаю, что этот метод можно вызвать из произвольного потока и, при этом, функция на которую указывает *procAddr будет заведомо выполнена в контексте приложения? Если так, то в эту функцию и надо упаковать вызов sendStringToExecute, что решило бы проблему, описанную в посте №6.

p.s.
Не могу найти acedPostCommand в документации ObjectARX  :cry:

Re: Фоновая обработка чертежа

Пастух пишет:

Правильно ли я понимаю, что этот метод можно вызвать из произвольного потока и, при этом, функция на которую указывает *procAddr будет заведомо выполнена в контексте приложения?

Нет. Только из потока связанного с одним из документов или приложением.

Пастух пишет:

Не могу найти acedPostCommand в документации ObjectARX

Значит она попрежнему недокументированная.
P.S.: Использовать мультизадачность в AutoCAD можно так: http://adndevblog.typepad.com/autocad/2 … ctarx.html

Re: Фоновая обработка чертежа

Жаль. Имя метода выглядит таким многообещающим... :(
Спасибо за ссылку. То, что нужно!

p.s.
Александр. Буду тебе признателен, если подскажешь, как найти декорированные имена для acedPostCommand для 32х и 64х разрядных AutoCAD 2014 (мне для P/Invoke). Я пытаюсь вернуться из двухлетнего небытия, но напрочь всё забыл.

Re: Фоновая обработка чертежа

ObjectARX:
x86: 

int __cdecl acedPostCommand(wchar_t const *);

x64: 

int __cdecl acedPostCommand(wchar_t const * __ptr64);

AutoCAD .NET API:
x86:

EntryPoint = "?acedPostCommand@@YAHPB_W@Z"

x64:

EntryPoint = "?acedPostCommand@@YAHPEB_W@Z"

из accore.dll

Re: Фоновая обработка чертежа

Спасибо.