简体   繁体   English

使用Qt中的工作线程将数据写入文件的正确方法是什么?

[英]What is the correct way to write data to a file using worker thread in Qt?

I am developing an application in Qt, which is UI intensive. 我正在Qt中开发一个UI密集型的应用程序。 It is UI intensive because, my application displays logs,which come at a very high speed and UI has to reflect that. 这是UI密集型的,因为我的应用程序显示日志,而日志的速度非常快,并且UI必须反映出来。

Now after the number of logs exceed a certain amount, My previous logs will start to get deleted, because my UI window has a limit(100000 logs, to keep app fast). 现在,当日志数量超过一定数量后,我的以前的日志将开始被删除,因为我的UI窗口有一个限制(100000个日志,以保持应用程序快速运行)。

So in order to save the old logs , I want to write the old logs to a file, before they get deleted. 因此,为了保存旧日志,我想在删除旧日志之前将其写入文件。

Problem 问题

If I write the file in main thread,my UI hangs(becomes very slow). 如果我在主线程中写入文件,我的UI会挂起(变得非常慢)。 So I decided to write file in a worker thread. 因此,我决定在工作线程中写入文件。 This is what I did this: 这就是我这样做的:

I made my own class WorkerThread that inherits class QThread and inside that class run() method, I write the data to a file. 我创建了自己的类WorkerThread ,该类继承了QThread类,并在该类的run()方法内部,将数据写入了文件。

The data that I want to write is stored in threads member variables itself: 我要写入的数据存储在线程成员变量本身中:

So my code is: 所以我的代码是:

Some other class function . 其他一些类的功能 . . .

WorkerThread *workerThread = new WorkerThread();
connect(workerThread, SIGNAL(resultReady()), workerThread, SLOT(quit()));
workerThread->attribute1 = dataToWrite1;
workerThread->attribute2 = dataToWrite2;
workerThread->start();

WorkerThread class WorkerThread类

class WorkerThread : public QThread
{
Q_OBJECT

public:

  QString attribute1;
  QString attribute2;  

protected:
    void run() {    
            // DELIMITER IS ..:  //                 

            QFile myFile("C:/shiftedlines/myFile.txt");
            if(myFile.open(QIODevice::WriteOnly|QIODevice::Append))
            {    
                QTextStream stream(&myFile);
                stream<< attribute1<<"..:";
                stream<< attribute2<<"\n";   
            }
        emit resultReady();
    }
signals:
    void resultReady();
};

But after writing about 500 lines, my application crashes . 但是写了大约500行之后,我的应用程序崩溃了 How do I go about solving this problem? 我该如何解决这个问题?

This does not address the issue you are having but since you asked this in the comments, this is how I implemented such tasks in the past. 这不能解决您遇到的问题,但是由于您在注释中提出了这个问题,因此这就是我过去实现此类任务的方式。

worker class 工人阶级

class worker : public QObject
{
    Q_OBJECT

    public:
        worker();

    public slots:
        void start();

    signals:
        void finished();
};

main 主要

worker* cur_worker = new worker();

// move to its own thread
QThread* worker_thread = new QThread(this);
cur_worker->moveToThread(worker_thread);
QObject::connect(worker_thread, SIGNAL(started()), cur_worker, SLOT(start()));
QObject::connect(cur_worker, SIGNAL(finished()), worker_thread, SLOT(quit()));
QObject::connect(worker_thread, SIGNAL(finished()), worker_thread, SLOT(deleteLater()));

// start
worker_thread->start();

This example does not handle the destruction of the worker object, which in your case you probably want to do immediately. 此示例不处理worker对象的销毁,在您的情况下,您可能希望立即执行该销毁。

Writing to a file should be quite fast as long as it's done correctly. 只要正确完成,写入文件的速度就应该很快。

What is slow is not writing to the file, but opening it. 慢的不是写文件,而是打开文件。

Make sure you don't open / close the file each time you receive a log, but open the file in write only and append mode, and keep it open while your application is running and writing log. 确保您不会在每次收到日志时都打开/关闭文件,而是以只写和追加模式打开文件, 在应用程序运行和写入日志时保持打开状态

Usually you can write in recent SSD drive at a speed around 700MB/s of data, so I doubt that you would have any noticeable impact on the UI. 通常,您可以以大约700MB / s的速度写入最新的SSD驱动器,因此我怀疑您会对UI产生明显影响。


If you really want to go for thread (which IMO is probably overkill) don't forget that to be thread safe, you have to communicate with your thread using signals / slots. 如果您真的想使用线程(这可能是IMO的大材小用),请不要忘记确保线程安全,您必须使用信号/插槽与线程进行通信。

From your code, it seems you start a new thread for each log write, which each tries to open the file. 从您的代码看来,您为每次日志写入启动了一个新线程,每个线程都试图打开文件。 Your file can be written only by one thread at a time and this will be blocked by the system, so above 1 thread for writing into a file, it is useless to have more. 您的文件一次只能被一个线程写入,这将被系统阻止,因此上面有1个线程可以写入文件,那么拥有更多线程是没有用的。

Probably your threads hangs into trying to open the file which is already accessed by some other, and end up with hundreds of hanging threads which ends up in a memory overflow if you have them in the stack. 可能是您的线程陷入了试图打开已经被其他人访问的文件的困境,最终导致了数百个挂起的线程,如果您将它们放在堆栈中,则会导致内存溢出。

The roule of Open your file once and write as long as you have something to write also applies in the thread. 只要有写东西,一次打开文件并写的规则也适用于线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM