Вызов COM Interop API из фонового потока? - PullRequest
0 голосов
/ 27 октября 2011

Я создаю экземпляр класса обслуживания, который содержит компонент взаимодействия COM, который выполняет автоматизацию терминала.Я использую Task Library (TPL) от Microsoft.Я хочу сделать вызов COM-объекта из задачи TPL (фоновый поток), чтобы мой пользовательский интерфейс не зависал во время работы COM-объекта.

Однако, когда я вызываю свою первую функцию из фонового потока (который получает IntPtr), генерируется исключение COM, детализирующее HRESULT: 0xC0000005.

Я знаю, что это исключение нарушения доступа, и я думаю,Я неправильно использую свой объект.

Как я могу вызвать методы из COM-объекта, созданного в основном потоке из фонового потока?

public void Button1_Click(object sender, EventArgs e) 
{
    var comWrapper = new COMWrapper(); // A simple wrapper for a COM object

    Task.Factory
        .StartNew(() => LoadStuff(comWrapper))
        .ContinueWith(() => {
            // Output results...
        });
}

int LoadStuff(COMWrapper w)
{
    return w.LoadStuffFromCOM();
}

Метод, который вызывает COMобъект:

int LoadStuffFromCOM()
{
    string buffer;
    IntPtr pointer = Marshal.StringToHGlobalUni(buffer);

    return comObject.GetValue(pointer); // Exception here...
}

Ответы [ 3 ]

1 голос
/ 27 октября 2011

Многие устаревшие COM-объекты были созданы для запуска в настольном приложении.Это означает, что они ожидали запуска в потоке пользовательского интерфейса, причем насос сообщений Windows является единственным методом синхронизации.

Теперь вы пытаетесь запустить этот код в среде, о которой он, возможно, никогда не «слышал».Существует большая вероятность того, что вы нарушили предположения, сделанные автором при написании кода.

Код может сработать, если вы не нарушите предположения, но если вы это сделаете, то вы получитепроблема (или две, или две дюжины).

0 голосов
/ 14 апреля 2014

Возможно, объекты COM / OLE Interop работают в фоновом режиме, но они должны быть скомпилированы с правильной моделью потоков

В случае Delphi для MTA он должен быть скомпилирован

initialization
  TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic,
    ciMultiInstance, tmFree);
end.

В случае STA по умолчанию используется

initialization
  TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic,
    ciMultiInstance, tmApartment);
end.

Должно быть одинаково в C / C ++ и других неуправляемых языках

Более подробную информацию можно найти здесь: http://msdn.microsoft.com/en-us/library/ff647812.aspx#scalenetchapt07 _topic11

0 голосов
/ 01 сентября 2012

Если вы в отчаянии, вы можете создать целый отдельный процесс, который выполнил ком-код. Тогда только придется написать ipc

...