crossplatform.ru

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


  Ответ в Запуск QAxObject в другом потоке
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
Алексей Дата 1.4.2011, 17:58
  Вобщем судя по обсуждению на официальном форуме QAxObject при перемещениии в другой поток (moveToThread) не пакует дочерний ком-объект

Если кому-то интересна дальнейшая судьба вопроса:
http://bugreports.qt.nokia.com/browse/QTBUG-18521
Алексей Дата 31.3.2011, 18:05
 
Цитата(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 можно работать даже после перемещения

По сути получилось что ком объект привязался к потоку и с ним можно будет только через сигналы работать, хотя хотелось бы чтоб он только асинхронно инициализировался в другом потоке после чего забирался в основной.
BRE Дата 30.3.2011, 19:27
  Если не ошибаюсь, в другом потоке нужно инициализировать COM.
Смотри на CoInitializeEx(...)
Алексей Дата 30.3.2011, 18:55
  Пытаюсь инициализировать 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 должно быть только в главном потоке.
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 2:10