Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 15.04.2019, 12:49   #1
Pavia
Лис
Профессионал
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 1,724
Репутация: 1946
По умолчанию Многопоточность Qt

Решил я разобраться с многопоточностью QT. И тут такая проблема с логами. У меня есть куча модулей в каждом подключаю #include <mylog.h>
Проблема в том что оно вылетает.

Стал разбираться выяснил что QT на каждый такой include создаёт свой *.obj файл. В результате QMutex в каждом модуле свой и как следствие не работает. Решено было сделать класс class mylog : public QTextStream
синглтоном и в него занести мьютекс.

2. Вначале хотел использовать Q_GLOBAL_STATIC_WITH_ARGS() но он на каждый поток создаёт свой объект. Решено было использовать общую память.

Код:

QSharedMemory shmem; // <-храним в описании класса

shmem.create("<Unique name>"); 
if (shmem.attach())
{
    isRunning = true;
}
else
{
    isRunning = false;
}

Хорошо отрабатывает, но проблема с размножением класса осталась.
В Delphi я бы сделал self:=shmem.data(); Но тут с++
А он не даёт подменить указатель
this=shmem.data();

Городить синглтон не стал, ограничился указателем на мьютекс.

Код:

#include <QCoreApplication>
#include <mylog.h>
#include <agent.h>

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

    logglobal();

    Agent ag;
    Agent ag1;
    return a.exec();
}

Код:

#include "agent.h"
#include <iostream>
#include <QObject>

Agent::Agent(QObject *parent) :
    QObject(parent)
{

    TheadWoker = new QThread(this);
    this->moveToThread(TheadWoker);
    connect(TheadWoker,SIGNAL(started()), this, SLOT(started()));
    TheadWoker->start();
}

void Agent::started()
{
    this->startTimer(1000,Qt::PreciseTimer);
}

void Agent::timerEvent(QTimerEvent *event)
{
    qDebug() << "Thead ID:"<< TheadWoker->currentThreadId() << " Timer ID:" << event->timerId();
    for(int i=0; i<rand(); i++)
    {
        std::cout << "i";
    }
}

Код:

#include "mylog.h"
#include <QFile>
#include <QDate>
#include <QMutex>
#include <QString>
#include <iostream>


Q_LOGGING_CATEGORY(lError,"error")
Q_LOGGING_CATEGORY(lInfo,"info")
Q_LOGGING_CATEGORY(lDebug,"debug")



void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    MyLog *logging=logglobal;
    logging->Mutex->lock();
    if ((0==QString::compare(context.category,"common")) && (logging->logfilter<0)) return;
    if ((0==QString::compare(context.category,"error")) && (logging->logfilter<1)) return;
    if ((0==QString::compare(context.category,"info")) && (logging->logfilter<2)) return;
    if ((0==QString::compare(context.category,"worning")) && (logging->logfilter<3)) return;
    if ((0==QString::compare(context.category,"debug")) && (logging->logfilter<4)) return;

    QDateTime dateTime=QDateTime::currentDateTime();
    *logging << " datatime="<< dateTime.toString("yyyy-MM-ddTHH:mm:ss:zzz")<< ": <" << context.category<<">"<< msg << endl;
    if ((logging->timer.elapsed()>=flushInterval_Logger) || (type>2))
    {
        logging->flush();
        logging->timer.restart();
    }
    logging->Mutex->unlock();
}

MyLog::MyLog(QString dirPath) :
    QTextStream()
{
    shmem=new QSharedMemory("<Name1>");

    if (shmem->attach())
    {
        Mutex=(QMutex *)(*((int*)shmem->data()));

    } else
    {
    shmem->create(8);
    *((int*)(shmem->data()))=int(&FMutex);
    Mutex=&FMutex;
    std::cout <<"MyLog.This:"<< this <<std::endl;
    }
    {
    timer.start();
    if (!openlog(dirPath)) {

        std::cout << ""Не могу создать файл лога. В директории: '" << dirPath.toStdString() <<"'" << std::endl;
        abort();
    }
    logleval=0;
    logfilter=5;
    qInstallMessageHandler(myMessageHandler);
    }
}


bool MyLog::openlog(QString filename)
{
    QFile *logfile= new QFile(filename+QDateTime::currentDateTime().toString("yyyy_MM_dd_HH.log"));
    if (!logfile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
        return false;
    this->FileName=logfile->fileName();
    this->flush();
    this->setDevice(logfile);
    return true;
}

Собственно вопрос как вы думаете тут есть ошибки или нету? Или у кого какие идеи? Раньше без глобального мьютекса код вылетал раз в 5-8*60 минут.
Как вы думаете увеличение числа потоков приведёт к ускорение вылетов?
__________________
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Многопоточность oksanavol Помощь студентам 0 14.06.2017 15:44
WPF и многопоточность Selestis WPF, UWP, WinRT, XAML 2 26.05.2012 22:14
Многопоточность lalilulelo Операционные системы общие вопросы 20 16.04.2012 19:33
Многопоточность t2skler Общие вопросы C/C++ 4 16.04.2012 14:24
многопоточность losbl9 Компоненты Delphi 2 16.01.2012 23:16


06:37.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru