crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Запуск QAxObject в другом потоке
Алексей
  опции профиля:
сообщение 30.3.2011, 18:55
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 37
Регистрация: 29.8.2010
Пользователь №: 1988

Спасибо сказали: 0 раз(а)




Репутация:   0  


Пытаюсь инициализировать COM-объект в другом потоке, Для этого использую класс TestConnector
testconnector.h
#ifndef TESTCONNECTOR_H
#define TESTCONNECTOR_H

#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>
#include <QThreadPool>
#include <QObject>

class TestConnector : public QObject, public QRunnable
{
    Q_OBJECT

public:
    TestConnector(QThread *recieveThread);
    void run();
    void setRecieveThread(QThread *t);

signals:
    void testConnectionFailed();
    void testConnected(QAxObject *ax);

protected:
    QThread *recieveThread;
};

#endif // TESTCONNECTOR_H
testconnector.cpp
#include "testconnector.h"
#include <QDebug>

TestConnector::TestConnector(QThread *recieveThread) :
    QObject(0)
{
    setRecieveThread(recieveThread);
}

void TestConnector::setRecieveThread(QThread *t)
{
    this->recieveThread = t;
}

void TestConnector::run()
{
    qDebug("TestConnector: Connecting to Ax");
    QAxObject *ax = new QAxObject("Word.Application", 0);

    if(ax->isNull())
    {
        qCritical("TestConnector: Ax connection failed");
        delete ax;
        ax = 0;
        emit testConnectionFailed();
    }
    else
    {
        qDebug("TestConnector: Ax connected successfully");
        ax->moveToThread(recieveThread);
        emit testConnected(ax);
    }
}


Запускаю:
    TestConnector *tc = new TestConnector(this->thread());
    connect(tc, SIGNAL(testConnected(QAxObject*)), this, SLOT(testConnected(QAxObject*)));
    connect(tc, SIGNAL(testConnectionFailed()), this, SLOT(testConnectionFailed()));
    QThreadPool::globalInstance()->start(tc);


Получаю
(Info) TestConnector: Connecting to Ax
(Warning) QAxBase::setControl: requested control Word.Application could not be instantiated
(Error) TestConnector: Ax connection failed


В основном потоке QAxObject *ax = new QAxObject("Word.Application", 0); выполняется без ошибок. Вроде в документации нигде не написано, что QAxObject должно быть только в главном потоке.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 30.3.2011, 19:27
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Если не ошибаюсь, в другом потоке нужно инициализировать COM.
Смотри на CoInitializeEx(...)


Сообщение отредактировал BRE - 30.3.2011, 19:28
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей
  опции профиля:
сообщение 31.3.2011, 18:05
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 37
Регистрация: 29.8.2010
Пользователь №: 1988

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 30.3.2011, 22:27) *
Если не ошибаюсь, в другом потоке нужно инициализировать COM.
Смотри на CoInitializeEx(...)

Да и вправду помогло, только с перемещением в другой поток возникли проблемы

Сделал следующее (изменил только run()):
testconnector.h
#ifndef TESTCONNECTOR_H
#define TESTCONNECTOR_H

#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>
#include <QThreadPool>
#include <QObject>

class TestConnector : public QObject, public QRunnable
{
    Q_OBJECT

public:
    TestConnector(QThread *recieveThread);
    void run();
    void setRecieveThread(QThread *t);

signals:
    void testConnectionFailed();
    void testConnected(QAxObject *ax);

protected:
    QThread *recieveThread;
};

#endif // TESTCONNECTOR_H
testconnector.cpp
#include "testconnector.h"
#include <QDebug>
#include <shlobj.h>

TestConnector::TestConnector(QThread *recieveThread) :
    QObject(0)
{
    setRecieveThread(recieveThread);
}

void TestConnector::setRecieveThread(QThread *t)
{
    this->recieveThread = t;
}

void TestConnector::run()
{
    qDebug("TestConnector: Initializing COM library");
    HRESULT h_result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    switch(h_result)
    {
    case S_OK:
        qDebug("TestConnector: The COM library was initialized successfully on this thread");
        break;
    case S_FALSE:
        qWarning("TestConnector: The COM library is already initialized on this thread");
        break;
    case RPC_E_CHANGED_MODE:
        qWarning() << "TestConnector: A previous call to CoInitializeEx specified the concurrency model for this thread as multithread apartment (MTA)."
                << " This could also indicate that a change from neutral-threaded apartment to single-threaded apartment has occurred";
        break;
    }

    qDebug("TestConnector: Connecting to Ax");
    QAxObject *ax = new QAxObject("Word.Application", 0);

    if(ax->isNull())
    {
        qCritical("TestConnector: Ax connection failed");
        delete ax;
        ax = 0;
        emit testConnectionFailed();
    }
    else
    {
        qDebug("TestConnector: Ax connected successfully");
        ax->moveToThread(recieveThread);
        emit testConnected(ax);
    }
}

Инициализация и всё прочее происходит успешно, откликается на вызовы функций, но при работе с полученным указателем на com-объект, из другого потока (recieveThread), получаю:
(Warning) QAxBase: Error calling IDispatch member <Название любой вызываемой функции>: Unknown error

Или если не останавливать поток, то:
(Warning) QAxBase::dynamicCallHelper: Object does not support automation

При этом из потока TestConnector можно работать даже после перемещения

По сути получилось что ком объект привязался к потоку и с ним можно будет только через сигналы работать, хотя хотелось бы чтоб он только асинхронно инициализировался в другом потоке после чего забирался в основной.

Сообщение отредактировал Алексей - 31.3.2011, 18:07
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей
  опции профиля:
сообщение 1.4.2011, 17:58
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 37
Регистрация: 29.8.2010
Пользователь №: 1988

Спасибо сказали: 0 раз(а)




Репутация:   0  


Вобщем судя по обсуждению на официальном форуме QAxObject при перемещениии в другой поток (moveToThread) не пакует дочерний ком-объект

Если кому-то интересна дальнейшая судьба вопроса:
http://bugreports.qt.nokia.com/browse/QTBUG-18521
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 9.8.2020, 13:52