Создание экземпляра Windows Form из макроса в Excel вызывает диалоговое окно, в котором Microsoft Excel ожидает, пока другое приложение выполнит действие ole

Извиняюсь за то, что не могу опубликовать какие-либо примеры кода (я еще не смог преобразовать небольшую воспроизводимую кодовую базу, а код, который у меня есть, является проприетарным).

Моя ситуация такова: у меня есть надстройка Excel, разработанная с использованием ДНК Excel, которая извлекает данные из веб-службы REST, требующей аутентификации. Надстройка хранит учетные данные для каждого сеанса, но не сохраняется между экземплярами Excel. Также существует макрос, доступный для пользователей, который позволяет им вызывать код в надстройке для извлечения данных из веб-службы.

Проблема заключается в том, что если пользователь ранее не входил в систему, мы открываем диалоговое окно Windows Form с запросом учетных данных. Это прекрасно работает. После успешного входа в систему начинается наша логика (в одном тесте выполняется 6 одновременных запросов) для извлечения данных из веб-службы. Там немного назад и вперед (запросить данные, они неавторизованы, войти в систему, запросить снова, вытащить данные и т. д.). Если вход в систему происходит программно (форма Windows не представлена ​​и не создается), все работает нормально.

Проблема, которую я вижу, заключается в том, что когда задействованы Windows Forms, я вижу задержку в 1 минуту 29 секунд (плюс/минус несколько долей секунды) между авторизованным запросом и получением данных. Эта задержка приводит к диалоговому окну Excel: «Microsoft Excel ожидает, пока другое приложение выполнит действие ole». Другая неприятная вещь заключается в том, что все, что мы сделали, на самом деле произошло успешно, пользователь просто получает это диалоговое окно и должен нажать «ОК» (и столкнуться с ненужной задержкой).

Все указывает на то, что задержки происходят на стороне клиента. Если я полностью удалю диалоговое окно входа в Windows Forms, мы не увидим никаких задержек, и все действия завершатся без каких-либо запросов от Excel.

По прихоти я полностью удалил код для запроса реальных учетных данных и жестко закодировал учетные данные нашей тестовой учетной записи. И это работает нормально. Если я возьму тот же самый код и просто создам пустую форму Windows, то есть new System.Windows.Forms.Form();, и ничего с ней не сделаю, я получу точно такое же поведение в этой части наших запросов, все блокируется на 1 минуту 29 секунд. Затем наш запрос завершается успешно, но клиент получает вышеупомянутое диалоговое окно Excel.

У нас также есть точно такая же функциональность, представленная через элемент управления Ribbon, который работает нормально, только 2 отличия: 1. макросы не задействованы, 2. мы отображаем диалоговое окно прогресса, пока работа продолжается.

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

Я думал, что мы делаем что-то не так, пока я просто не создал пустую форму Windows Form (заметьте, она даже не показывалась, а просто создавалась) и не смог воспроизвести поведение.

Кто-нибудь видел это или знает, как решить?


person Nathan Ernst    schedule 24.01.2014    source источник


Ответы (1)


Это не ответ, но я не думаю, что он подойдет в качестве комментария. Также с текущей информацией я не уверен, что ответ возможен.

Да, конечно, код проприетарный. Тем не менее, вам придется показать некоторые из них, иначе это никуда не денется. Все, что я могу сделать прямо сейчас, это предложить кое-что посмотреть.

С надстройками может быть очень сложно узнать, в какой теме вы на самом деле находитесь. Непосредственно перед тем, как вы создадите форму входа, поместите эти строки:

    ApartmentState threadState = Thread.CurrentThread.GetApartmentState();
    if (threadState != ApartmentState.STA)
    {
        // put a break or some warning like console.Writeline(threadState);
    }

Если это не STA-поток, то экземпляр Window Message pump не может быть создан — что ж, это слишком сильно: помпы сообщений должны быть только в STA-потоках, и хотя я думаю, что они могут быть в MTA-потоке, это приведет к проблемам.

Если у вас есть ссылка на элемент пользовательского интерфейса, который наследуется от Control, вы можете проверить, требуется ли Invoking для его изменения:

if (control.InvokeRequired)
{
    // You're not on the GUI thread
}

Если что-то из этого не работает, вы, вероятно, не в той ветке, о которой думаете.

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

Просто некоторые вещи, чтобы попробовать.

person simon at rcl    schedule 24.01.2014
comment
Мне в голову пришло «государство-квартира»; Я не проверял, что это такое (завтра попробую). Еще одна странность, которую я обнаружил (и это мое исправление на данный момент), заключается в том, что WPF, похоже, не имеет такой же проблемы. Что касается того, где возникает задержка, это после первоначального запроса REST на вход в веб-службу для установления сеанса (помните, мы делаем это асинхронно в 6 разных потоках/сеансах). Все запросы зависают после получения первоначального успешного входа в систему, но до того, как мы сможем отправить реальный запрос. Отладчик показывает ожидание выполнения задач; http trace показывает завершение. - person Nathan Ernst; 30.01.2014
comment
Я убедился, что ApartmentState это STA. - person Nathan Ernst; 31.01.2014