Сборка .NET COM взаимодействует с Excel через BackgroundWorker - PullRequest
1 голос
/ 24 февраля 2011

Я пишу (и учу себя, как писать) экспериментальную сборку в VB.NET 3.5, которая предоставляется через COM, а затем вызывается из некоторого кода Excel VBA, чтобы инициировать экземпляр класса, который перехватывает некоторые события Excel, а затем выполняет некоторые функции активной книги в Excel.

Чтобы инициировать класс, ссылка на приложение Excel передается из VBA (я использую PIA для Excel в сборке).

Мне нужно было выполнить трудоемкую операцию с активной книгой из моей сборки, поэтому я решил использовать BackgroundWorker в WinForm, чтобы я мог отображать диалоговое окно хода выполнения операции, пока операция завершается в фоновом режиме.

Хотелось бы узнать, есть ли проблемы с взаимодействием с Excel через COM с использованием фонового рабочего? Причина для того, чтобы спросить, заключается в том, что основной класс в сборке содержит ссылку на объект приложения Excel, а затем он передается в BackgroundWorker, чтобы он мог определить активную книгу и затем выполнить с ней некоторые операции. Я получаю доступ только к самой книге (не к другим объектам) с помощью одной процедуры.

По какой-то причине у меня в голове возникает мысль, что Excel может не нравиться это - я прав?

Ответы [ 2 ]

2 голосов
/ 24 февраля 2011

Если вы ссылаетесь на это:

  • Получение вызова метода из VBA для вашего кода VB.NET
  • Выделение нового потока (или рабочего потока) и передачачерез ссылку на рабочую книгу (или на Excel.Application, Range; это не имеет значения) (через параметры, статистику ... это не имеет значения)
  • Использовать оригинальный поток для отображения пользовательского интерфейсав то время как фоновый поток обращается к Excel

Тогда нет;Вы не можете этого сделать.

Excel VBA - это среда STA.Весь доступ к объектной модели Excel, входящий и выходящий, должен осуществляться из одного потока.Вы также не можете выбрать нить;для начала это должен быть поток, вызвавший ваш метод.

Для запуска кода, обращающегося к Excel, из рабочего потока, вам придется «маршалировать» указатель интерфейса на ваш рабочий поток.Mashalling создает пару оболочек COM (называемых парами «прокси / заглушка»), которые при необходимости переносят вызов метода между потоками - это похоже на то, что происходит, когда вы используете метод Form.Invoke() в .NET.Я не знаю, как изо всех сил, как это сделать в .NET.В любом случае, это не будет мой первый подход.

Другой альтернативой является НЕ доступ к объекту Excel из вашего рабочего потока, а использование помощников в основном объекте формы (вам нужна форма, не так ли?).Пусть ваш рабочий поток вызывает этих помощников через Form.Invoke(), чтобы убедиться, что они запускаются из потока пользовательского интерфейса (потока, который VBA использовал для вызова вас).Функционально это то же самое, что и первая альтернатива, за исключением того, что .NET выполняет работу вместо COM.

Третий подход заключается в том, чтобы вообще не использовать рабочие потоки - сделать это способом VB: создать свой пользовательский интерфейсиз единственной нити;покажите это, а затем выполните свою работу из события Load формы.Время от времени вызывайте Application.DoEvents() (несколько раз в секунду), чтобы позволить интерфейсу работать с некоторой степенью схожести.

Четвертая альтернатива - перевернуть проблему.Используйте новый поток вместо потока пула (это то, что вы получаете от BackgroundWorker) и обрабатывайте пользовательский интерфейс оттуда.Здесь мы поменяемся ролями: основной поток выполнит сложную работу, а дополнительный поток создаст форму и покажет пользовательский интерфейс.Опять же, убедитесь, что вы используете Form.Invoke(), чтобы обновить окно прогресса.Убедитесь, что вы Dispose() ваша тема, когда вы закончите.Это может быть мой предпочтительный подход.

Или просто использовать указатель мыши в виде песочных часов ... Насколько "медленный" ваш "медленный"?

0 голосов
/ 24 февраля 2011

Не знаю много об использовании BackgroundWorker. Я работал над приложением Winforms, которое взаимодействовало с Excel через PIA и COM. Он использовал обычный старый делегат ThreadStart для ускорения потока, который отображал индикатор выполнения, пока файлы загружались в фоновом режиме. Работал нормально. Насколько я понимаю, BackgroundWorker работает примерно так же под покровом, поэтому я бы сказал, пойти на это.

...