Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt Синхронизация старта потоков


Автор: feanor59 12.10.2008, 15:41
И так. Нужен совет. 
Цель: синхронизировать старт потоков, т. е. добиться, чтобы инструкция, следующая после abstractThread.start(); выполнялась только после выполнения метода abstractThread.run(); причём желательно организовать незанятое ожидание.

Ниже приведены пара моих решений. Если есть варианты лучше, отпишите.
Код

//Вариант 1:
//здесь не реализовано незанятое ожидание
for (; !abstractThread.isRunning(););

//Вариант 2:
//здесь приходится вызывать лишний метод

class AbsThread : public QThread {
QMutex mutex;
...
void run() {
...
exec();
mutex.unlock();
}

void prestart() {
mutex.lock();
}

public slots:
void allSlots (...) {
QMutexLocker locker(mutex);
...
}
...
};

AbsThread abstractThread;
abstractThread.prestart();
abstractThread.start();


Проблема же такая возникла из-за того, что в run() инициализируется объект QTextStream, но иногда до этого выполняется один из слотов, как следствие - краш.

Автор: feanor59 12.10.2008, 19:04
мда. как выяснилось, рабочий только 1й вариант, остальные воспринимаются как дедлок.
UPD:  чорд... 1й вариант так же не катит...

Автор: JackYF 13.10.2008, 14:42
Я что-то не понял... потоков сколько?

Цитата(feanor59 @  12.10.2008,  14:41 Найти цитируемый пост)
что в run() инициализируется объект QTextStream, но иногда до этого выполняется один из слотов, как следствие - краш.

Это тоже не понял.

Автор: feanor59 13.10.2008, 15:01
Цитата(JackYF @ 13.10.2008,  14:42)
Я что-то не понял... потоков сколько?

Цитата(feanor59 @  12.10.2008,  14:41 Найти цитируемый пост)
что в run() инициализируется объект QTextStream, но иногда до этого выполняется один из слотов, как следствие - краш.

Это тоже не понял.

поток один, не считая основного, и этот поток с этим основным и надо синхронизировать.
вот пример:

в потоке есть 2 метода:
Код

void Logger::run() {
    log = new QFile("log.htm");    
    logStream = new QTextStream(log);    

    exec();    
}

void Logger::slotLogIt(<something>) {
    logStream << "something" << endl;
}

main выглядит так
Код

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Logger logger(NULL);

    QObject::connect(udpClient.get(), SIGNAL(logIt(LogType, QString&)), &logger, SLOT(slotLogIt(LogType, QString&)));

    logger.start();
    for (int i = 0; i < 100; ++i)
        udpClient->sendMsg((QString)"PING");

    return a.exec();
}

Дак вот. Метод run() выполняется позже, чем emit logIt() в методе sendMsg().
Я в курсе, что инициализацию можно в конструктор вынести (точнее я так и сделал), но, тем не менее, проблема осталась, как минимум exec() выполняется позже, чем надо.

Автор: JackYF 14.10.2008, 14:53
Цитата(feanor59 @  13.10.2008,  14:01 Найти цитируемый пост)
Logger logger(NULL);
    QObject::connect(udpClient.get(), SIGNAL(logIt(LogType, QString&)), &logger, SLOT(slotLogIt(LogType, QString&)));
    logger.start();

Дык... сделай "logger.start()" до QObject::connect.

Автор: feanor59 14.10.2008, 14:55
Цитата(JackYF @ 14.10.2008,  14:53)
Цитата(feanor59 @  13.10.2008,  14:01 Найти цитируемый пост)
Logger logger(NULL);
    QObject::connect(udpClient.get(), SIGNAL(logIt(LogType, QString&)), &logger, SLOT(slotLogIt(LogType, QString&)));
    logger.start();

Дык... сделай "logger.start()" до QObject::connect.

не, не вариант. по разному пробовал. результат один.

Автор: JackYF 14.10.2008, 17:38
А впиши-ка debug output'ы в местах, которые должны быть синхронизированы.
Возможно, просто не ходят сообщения из-за того, что QCoreApplication ещё не запущен.

Автор: feanor59 23.10.2008, 11:07
так. извиняйте, что долго не отписывал, другие дела были. дак вот, качественное снабжение кода qDebug'ами выявили косяк следующего содержания. Инициализация QCoreApplication не успевает к первой высылке сигнала в коде, следовательно сигнал не высылается.
Я, правда, не совсем понимаю связь этого факта с проблемой старта потоков, но так или иначе проблема есть. Как то можно заставить код ждать инициализыции кор апликейшена и как всё таки это может помочь в разрешении проблемы потоков?

Автор: JackYF 23.10.2008, 19:41
Цитата(feanor59 @  23.10.2008,  10:07 Найти цитируемый пост)
Как то можно заставить код ждать инициализыции кор апликейшена

вынести весь главный код main в отдельный поток? smile

Автор: feanor59 23.10.2008, 19:48
кстати. хорошая идея. Вынести в поток всю инициализацию всего, что возможно, и повесить на это дело сплеш.
Попробую. 

UPD: а как это спасёт ситуацию с синхронизацией запуска потоков?

Автор: JackYF 24.10.2008, 13:45
Тогда такой вариант: стартовать logger.start() только по сигналу, сделать emit сигнал перед app.exec(). Этот сигнал, по идее, будет выполнен после app.exec(), следовательно, к моменту запуска потока сигналы-слоты уже в строю.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)