Parallel.Invoke

Автор Тема: Parallel.Invoke  (Прочитано 11078 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Parallel.Invoke
« : 08-11-2020, 21:20:35 »
Всех приветствуют. Кто-нибудь на форуме пользуется в плагинах к AutoCAD Parallel.Invoke иди другими многопоточными фишками?
Меня интересует, вот что:

Такой шаблон не работает
Код - C# [Выбрать]
  1. Parallel.Invoke(
  2.   () =>
  3.   {
  4.     //Запускается и что-то делает не AutoCAD, например Excel
  5.   },
  6.   () =>
  7.   {
  8.     //Тут что-то делает AutoCAD, например добавляет лист и производит на нём операции
  9.   });

А вот такой работает
Код - C# [Выбрать]
  1. Parallel.Invoke(
  2.   () =>
  3.   {
  4.     //Тут что-то делает AutoCAD, например добавляет лист и производит на нём операции
  5.   },
  6.   () =>
  7.   {
  8.     //Запускается и что-то делает не AutoCAD, например Excel
  9.   });

Отмечено как Решение Lemieux 08-11-2020, 21:55:13

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13898
  • Карма: 1790
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Parallel.Invoke
« Ответ #1 : 08-11-2020, 21:23:45 »
Lemieux,
Обращение к AutoCAD API (любое - .NET/VisualLisp/VBA/ObjectARX) допустимо только из основного потока. Многопоточное обращение к AutoCAD запрещено. Точка!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #2 : 08-11-2020, 21:31:01 »
Lemieux,
Обращение к AutoCAD API (любое - .NET/VisualLisp/VBA/ObjectARX) допустимо только из основного потока. Многопоточное обращение к AutoCAD запрещено. Точка!
Получается, что во втором варианте я обращаюсь из основного потока, если всё работает?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13898
  • Карма: 1790
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Parallel.Invoke
« Ответ #3 : 08-11-2020, 21:36:06 »
Получается, что во втором варианте я обращаюсь из основного потока, если всё работает?
Видимо да, хотя я не видел, чтобы это было где-то документировано. Но если вдруг, в какой-то ситуации это окажется нет так, то пользователя твоей программы сразу возникнут проблемы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #4 : 08-11-2020, 21:55:08 »
Обращение к AutoCAD API (любое - .NET/VisualLisp/VBA/ObjectARX) допустимо только из основного потока. Многопоточное обращение к AutoCAD запрещено. Точка!
Что и требовалось доказать.
С Parallel.ForEach не получилось, выдаёт ошибку "Операция является недопустимой из-за текущего состояния объекта", когда в транзакции вызываю метод GetObject(). Хотя первые двадцать итераций ошибки не выдавало, но мне лень щелкать 200 раз. Но меня смутило то, что во время итерации отладчик подсвечивал не в цикле, а в LINQ запросе (я блоки в пространстве модели получаю через LINQ запрос).

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 839
  • Карма: 168
    • Мои плагины к Автокаду
Re: Parallel.Invoke
« Ответ #5 : 08-11-2020, 22:22:17 »
Если есть в самом деле сложная задача, то ее можно распараллелить. Просто надо считать данные из чертежа в свои структуры, обработать параллельно, не вызывая API, и потом уже сохранять результаты в чертеж в главном процессе. По моему опыту структуры из API и их методы можно вызывать из других потоков безболезненно (Point2d, Vector3d и т.п.) Еще ProgressMeter вызываю - ничего, не фаталит. Но конечно не объекты из транзакций получать.

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #6 : 09-11-2020, 20:50:45 »
Если есть в самом деле сложная задача, то ее можно распараллелить. Просто надо считать данные из чертежа в свои структуры, обработать параллельно, не вызывая API, и потом уже сохранять результаты в чертеж в главном процессе. По моему опыту структуры из API и их методы можно вызывать из других потоков безболезненно (Point2d, Vector3d и т.п.) Еще ProgressMeter вызываю - ничего, не фаталит. Но конечно не объекты из транзакций получать.
Зачем делать двойную работу? Сначала считывать, потом обрабатывать и потом всё это объединять? Я тут попробовал провести эксперимент. Думал получу все блоки из пространства модели, получу количество доступных потоков, разобью список на количество потоков и сделаю массив из Action с нужными мне действиями по чтению нужной информации из блоков и засуну эти Action в Parallel.Invoke. Но AutoCAD ругается, странно, что фича с Excel/Word работает.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 839
  • Карма: 168
    • Мои плагины к Автокаду
Re: Parallel.Invoke
« Ответ #7 : 09-11-2020, 21:12:29 »
Про это уже было сказано вполне однозначно. Читать и записывать данные в чертеж -только в одном потоке. Автокад не эксел, шуток не понимает. Зачем вы опять экспериментируете?
И нет никакой двойной работы - есть работа со считанными данными. И если она достаточно большая, то имеет смысл отделять чтение/хранение/обработку/запись.  Если несущественная - не имеет смысла - работайте в одном потоке.

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #8 : 09-11-2020, 21:23:06 »
Зачем вы опять экспериментируете?
Потому что интересно.

PS пришла идея с "AcCoreConsole.exe", но пока не буду городить огород, так как действительно больших проектов нет. Но если буду проекты где 500-1000 блоков в пространстве модели, то буду думать. Или если будет свободное время.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 839
  • Карма: 168
    • Мои плагины к Автокаду
Re: Parallel.Invoke
« Ответ #9 : 09-11-2020, 22:16:22 »
1000 блоков - это мизер. Сейчас делал плагин для чистки чертежа после импорта pdf. Там по 350 тысяч объектов сразу читывать приходится. Панель свойств впадает в ступор. Но простой цикл чтения foreach без малейшей параллельности считывает это за 2 секунды. Что тут параллелить и зачем?

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #10 : 10-11-2020, 08:08:56 »
1000 блоков - это мизер. Сейчас делал плагин для чистки чертежа после импорта pdf. Там по 350 тысяч объектов сразу читывать приходится. Панель свойств впадает в ступор. Но простой цикл чтения foreach без малейшей параллельности считывает это за 2 секунды. Что тут параллелить и зачем?
Что считывает, блоки из пространства модели? Но мне надо работать с атрибутами блоков, которых в блоке может быть много.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 554
  • Карма: 119
Re: Parallel.Invoke
« Ответ #11 : 10-11-2020, 12:31:24 »
Что считывает, блоки из пространства модели? Но мне надо работать с атрибутами блоков, которых в блоке может быть много.
AutoCAD это хорошо оптимизированное однопоточное приложение при работе с БД чертежа. По опыту, производительности хватает на обработку/изменение данных.

мне надо работать с атрибутами блоков, которых в блоке может быть много.
Ты можешь в основном потоке считать информацию из атрибутов в массивы/классы, обработать Parallel.Invoke и в основном потоке изменить атрибуты.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13898
  • Карма: 1790
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Parallel.Invoke
« Ответ #12 : 10-11-2020, 12:41:19 »
Lemieux,
У меня есть приложение DWGCONVERT, которое полностью проходит по ВСЕМУ чертежу и меняет кодировку текстов, атрибутов, наименований слоёв, блоков, стилей и т.д. Так вот какой-нибудь чертеж может открываться несколько минут, а программа отрабатывает (модифицирует его полностью) за секунды. И при этом она однопоточная.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 393
  • Карма: 21
Re: Parallel.Invoke
« Ответ #13 : 10-11-2020, 14:28:59 »
Ты можешь в основном потоке считать информацию из атрибутов в массивы/классы, обработать Parallel.Invoke и в основном потоке изменить атрибуты.
Так я нигде не писал, что мне надо изменять атрибуты, я их считываю, но у меня 5 условий при считывании атрибутов. И в цикле происходит анализ всех атрибутов, а запись в нужные массивы происходит не из всех атрибутов, а только удовлетворяющих условиям.

а программа отрабатывает (модифицирует его полностью) за секунды
Допустим у меня команда отрабатывает за 5 секунд, но был интересен сам факт распараллеливания и новой информации.

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 554
  • Карма: 119
Re: Parallel.Invoke
« Ответ #14 : 10-11-2020, 15:17:22 »
но у меня 5 условий при считывании атрибутов. И в цикле происходит анализ всех атрибутов, а запись в нужные массивы происходит не из всех атрибутов, а только удовлетворяющих условиям.

Допустим у меня команда отрабатывает за 5 секунд, но был интересен сам факт распараллеливания и новой информации.

Разбей задачу на 2 части:
1. Считывай все атрибуты в массивы(или что у тебя там) за один проход и замерь время. 
2. Посмотри сколько времени занимает анализ атрибутов.

Вполне возможно, что 4 секунды тратились на анализ. Вот и будешь оптимизировать его хоть с Parallel.Invoke, хоть без.