Если вы ссылаетесь на это:
- Получение вызова метода из 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()
ваша тема, когда вы закончите.Это может быть мой предпочтительный подход.
Или просто использовать указатель мыши в виде песочных часов ... Насколько "медленный" ваш "медленный"?