Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: OKTA от Сентябрь 12, 2012, 13:39



Название: [РЕШЕНО] потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 13:39
Товарищи! Не могу вдуплить, в чем проблема! Поведение какое-то ну крайне своеобразное! Приведу кусок кода!
Такой вот main:
Код:
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    AppSettings aps;

    uMail *ut = new uMail(&aps);

    GUIAdapter *ga = new GUIAdapter(ut);

    QThread testThread;
    ut->moveToThread(&testThread);
    testThread.start();

    ut->run();

    return a.exec();
}

Кусочек GUIAdapter.h :
Код:
class GUIAdapter : public QObject {

    Q_OBJECT

    // Engine Object
    uMail *eg;

    QDeclarativeView *mainWin, *currentWin;
    QObject *mainWinObj;
    QObject *flipobjFirstEnter;

И кусочек GUIAdapter.cpp:
Код:
void GUIAdapter::startMainWindow(){
    //
      
    QDeclarativeView *mw = new QDeclarativeView();

    currentWin = mainWin = mw;
    currentWin->installEventFilter(this);

В чем, собственно, проблема! GUIAdapter (ga) и uMail (ut) работают в разных потоках - первый остается в главном и в нем работает графика, а второй служит "движком" и направляется в отдельный поток. Но при старте оказывается, что все объекты QDeclarativeView, объявленные в GUIAdapter.h и использованные в cpp-шнике каким-то образом перемещаются в поток с uMail - Как такое может быть??


Название: Re: потоки и GUI
Отправлено: Bepec от Сентябрь 12, 2012, 13:45
Код:
  GUIAdapter *ga = new GUIAdapter(ut);


Название: Re: потоки и GUI
Отправлено: mutineer от Сентябрь 12, 2012, 13:45
Вслед за объектом перемещаются и его чилдрены


Название: Re: потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 13:49
Но ga при этом не перемещается в другой поток! Перемещаются только QDeclarativeView внутри! + ut передается как указатель и используется только для вызова методов uMail. Не бейте, если не понимаю чего-то)


Название: Re: потоки и GUI
Отправлено: mutineer от Сентябрь 12, 2012, 13:51
void GUIAdapter::startMainWindow() в каком потоке вызывается? В том же и будет жить созданный в нем QDeclarativeView


Название: Re: потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 13:56
Вызывается вот так:
Код:
 QObject::connect(ut, SIGNAL(startMainWindow()),
                     ga, SLOT(startMainWindow()), Qt::DirectConnection);
Коннект прописан в main, соответственно в главном потоке и вызывается! Проверяю специально -GUIAdapter ga И QApplication a В одном потоке, а uMail в отдельном!


Название: Re: потоки и GUI
Отправлено: mutineer от Сентябрь 12, 2012, 13:59
Qt::DirectConnection означает что слот будет вызван прямо из места испускания сигнала. А сигнал испускается из объекта ut, который в другом потоке. Значит и слот будет вызван в том же потоке


Название: Re: потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 14:01
Разве?? Я использовал его, искренне веря в
Код:
Qt::DirectConnection	1	The slot is invoked immediately, when the signal is emitted.


Название: Re: потоки и GUI
Отправлено: mutineer от Сентябрь 12, 2012, 14:03
Слот вызовется немедленно, то есть будет непосредственный вызов слота из тела сигнала. Непосредственный вызов между потоками в C++ невозможен


Название: Re: потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 14:07
Вот фак)) Точно) Спасибо большущее!!)) Т.е. как понимаю, используя прямое соединение слот вызывается сразу же, но из потока сигнала, а чтобы этого не происходило, надо использовать дефолтное AutoConnection?


Название: Re: потоки и GUI
Отправлено: mutineer от Сентябрь 12, 2012, 14:08
Да, либо QueuedConnection, если хочешь чтобы вызов всегда проходил через EventLoop, независимо от потоков отправителя/получателя


Название: Re: потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 14:12
Большое спасибо!)


Название: Re: [РЕШЕНО] потоки и GUI
Отправлено: OKTA от Сентябрь 12, 2012, 14:51
Вот, если кто заглянет:

Код:
Signals and Slots Across Threads
Qt supports these signal-slot connection types:
Auto Connection (default) If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection."
Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
Blocking Queued Connection The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns. Note: Using this type to connect objects in the same thread will cause deadlock.
Unique Connection The behavior is the same as the Auto Connection, but the connection is made only if it does not duplicate an existing connection. i.e., if the same signal is already connected to the same slot for the same pair of objects, then the connection is not made and connect() returns false.
The connection type can be specified by passing an additional argument to connect(). Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.
QObject::connect() itself is thread-safe.
The Mandelbrot example uses a queued connection to communicate between a worker thread and the main thread. To avoid freezing the main thread's event loop (and, as a consequence, the application's user interface), all the Mandelbrot fractal computation is done in a separate worker thread. The thread emits a signal when it is done rendering the fractal.