Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

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

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

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.04.2019, 11:49   #1
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию Многопоточность 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 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Многопоточность oksanavol Помощь студентам 0 14.06.2017 14: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