Использование потоков (Thread) для фоновой обработки
Вопрос:Внутри моей команды я хочу запустить фоновую задачу для синхронизации с базой данных. Как только эта задача заканчивается я хотел бы при помощи AutoCAD .NET API сделать некоторые изменения в базе данных. Однако, когда я вызываю функции AutoCAD API из этой задачи, они не работают. Например, the MdiActiveDocument равен null.
Ответ:
AutoCAD .NET API не позволяют использовать мультизадачность. Необходимо вызывать функции API из главной задачи.
Если вы находитесь в другой задаче, вам необходимо настроить вызов из главной задачи. Самый простой способ достичь этого – это создать объект System.Windows.Forms.Control в главной задаче и использовать его метод Invoke() для запуска функции которая и выполнит окончательную обработку.
Следующий пример показывает это:
- using System;
- using Autodesk.AutoCAD.Runtime;
- using System.Windows.Forms;
- using Autodesk.AutoCAD.EditorInput;
- using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.Geometry;
- namespace BackgroundProcess
- {
- public class Commands : IExtensionApplication
- {
- static Control syncCtrl;
- public void Initialize()
- {
- // Создаем элемент управления для перенаправления
- // вызова в главную задачу
- syncCtrl = new Control();
- syncCtrl.CreateControl();
- }
- public void Terminate()
- {
- }
- void BackgroundProcess()
- {
- // Это чтобы продемонстрировать фоновый процесс
- System.Threading.Thread.Sleep(5000);
- // Теперь нужно перенаправить вызов в главную задачу
- // Я не знаю в каком случае может быть false в этом контексте,
- // но на всякий случай проверяю
- if (syncCtrl.InvokeRequired)
- syncCtrl.Invoke(
- new FinishedProcessingDelegate(FinishedProcessing));
- else
- FinishedProcessing();
- }
- delegate void FinishedProcessingDelegate();
- void FinishedProcessing()
- {
- // Если мы хотим модифицировать базу данных, в этом случае
- // мы должны заблокировать документ, как в контексте приложения
- Document doc = acApp.DocumentManager.MdiActiveDocument;
- using (doc.LockDocument())
- {
- using (Transaction tr =
- doc.Database.TransactionManager.StartTransaction())
- {
- BlockTable bt =
- (BlockTable)tr.GetObject(
- doc.Database.BlockTableId, OpenMode.ForRead);
- BlockTableRecord ms = (BlockTableRecord)tr.GetObject(
- bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
- Line line =
- new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));
- ms.AppendEntity(line);
- tr.AddNewlyCreatedDBObject(line, true);
- tr.Commit();
- }
- }
- // Так же напишем в командную строку
- Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
- ed.WriteMessage("Фоновая задача завершилась!\n");
- }
- [CommandMethod("ProcessInBackground")]
- public void ProcessBackground()
- {
- // Допустим, что мы получили какие-то данные из чертежа
- // и хотим их обработать в фоновой задаче
- System.Threading.Thread thread =
- new System.Threading.Thread(
- new System.Threading.ThreadStart(BackgroundProcess));
- thread.Start();
- Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
- ed.WriteMessage(
- "Фоновая обработка запущена." +
- "Можете работать как обычно.\n");
- }
- }
- }
Источник: http://adndevblog.typepad.com/autocad/2012/06/use-thread-for-background-processing.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=973
Опубликовано 23.09.2014