2010-04-06 9 views
2

Я делаю COM-взаимодействие COM с Excel и другим программным обеспечением автоматизации Office.COM Interop - Подождите, пока Excel завершит работу

Co-Worker сказал мне, что мне нужно дождаться, когда эти серверы автоматизации станут готовыми после выдачи им команды.

Я, однако, не вижу цели этого, так как не все вызовы блокируются, пока сервер автоматизации не завершит задание?

Например, я обычно пишу:

 
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) 
o.Property ' could throw COM exception!!???? 

Мой коллега говорит, что мне нужно спать после этого вызова, потому что Automation Server может все еще работать над созданием и инициализации объекта.

 
Dim o as AutomationObject = AutomationServer.CreateObject(x, y, z) 
Threading.Sleep(5000) ' wait for AutomationServer to "become ready" 
o.Property ' could still throw COM exception!!???? 

У меня есть проблема с этим состоит в том, что AutomationServer вызовы должны блокировать, пока AutomationServer не закончит или завершает то, что она работает или, по крайней мере, он должен быть цикл проверки, если «о» ничего нет, но это не имеет никакого смысла, потому что, как только звонок вернется, он будет сделан!

Мой вопрос: есть ли какие-либо преимущества для Спящего после вызова AutomationServer? Есть ли способ «подождать» до тех пор, пока AutomationServer не завершится (если он фактически не заблокирован)?

ответ

1

Простой способ справиться с этим ниже. В последнее время мне пришлось взаимодействовать с Visual Studio, и я нашел, что это сработало хорошо, если вы готовы быстро выйти из COM-объекта, становясь бесконечно занятым. Смотрите, если это будет работать для вас:

delegate void COMWrapper(); 

    private void MakeRiskyCOMCall(COMWrapper doThis) 
    { 
     bool sendAgain = true; 
     int count = 0; 

     while (sendAgain) 
     { 
      try 
      { 
       doThis(); 
       sendAgain = false; 
      } 
      catch (COMException ex) 
      { 
       System.Threading.Thread.Sleep(50); 
       sendAgain = count > 100 ? false : true; 
       if (!sendAgain) 
       { 
        throw; 
       } 
      } 
      finally { count++; } 
     } 
    } 

После того, как этот делегат и метод в области видимости, то вот примеры вызова метода и доступа к свойству с помощью анонимного делегирования.

// property access 
    vsDisplay display; 
    MakeRiskyCOMCall(delegate() { display = dte.DisplayMode; }); 
    if (display == null) 
     throw new Exception("VS Display not set");   

    //simple method call 
    MakeRiskyCOMCall(delegate() { dte.Solution.Close(true); }); 

Я намеренно спрятал COMException, так как я не хочу, но если вам это нужно просто установить переменную COMException в рамках метода MakeRiskyCOMCall, который контекстный в вызывающем методе. Вы также можете проверить конкретный HResult, который указывает на ожидание процесса занятости и более быстрое сбой для других HResults. Это решение является быстрым и позволяет избежать беспорядка COM-взаимодействия, и его недостатком является то, что он некрасивый, но он работает, и его легче понять для разработчиков вашего кода (я думаю).

1

Вы действительно можете получить исключение, обратившись к серверу автоматизации автоматизации, который занят. В случае Office один из способов может произойти, если у вас есть макрос, который запускается при открытии документа. У вас также возникнут проблемы, если вы подключитесь к экземпляру приложения Office, открывающего диалоговое окно.

This article описывает, как вы можете избежать этого, применяя обработчики ошибок IOleMessageFilter. Статья посвящена автоматизации Visual Studio, но принципы и методы одинаковы для автоматизации других серверов автоматизации вне процесса, таких как Office.

Смежные вопросы