<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Qt | 四種方式實現多線程導出數據功能

      前言

      在以往的項目開發中,在很多地方用到了多線程。針對不同的業務邏輯,需要使用不同的多線程實現方法,來達到優化項目的目的。本文記錄下在Qt開發中用到的多線程技術實現方法,以導出指定范圍的數字到txt文件為例,展示多線程不同的實現方式。
      示例已上傳到gittee,地址:https://gitee.com/zbylalalala1/qt_-thread-demo.git

      image-20250806095428714

      導出文件的示例工具類

      首先提供一個工具類,用于將指定范圍的數字寫入txt文件。

      #ifndef UTILITIES_H
      #define UTILITIES_H
      
      #include <QString>
      #include <QFile>
      #include <QTextStream>
      #include <QDateTime>
      #include <QDir>
      #include <QDebug>
      class Utilities
      {
      public:
          static bool writeNumbersToFile(int start, int end, const QString& prefix = "numbers")
          {
              if (start > end) {
                  qDebug() << "起始數字不能大于結束數字";
                  return false;
              }
              
              // 獲取當前時間并格式化為文件名
              QDateTime currentTime = QDateTime::currentDateTime();
              QString timeString = currentTime.toString("yyyy-MM-dd_hh-mm-ss");
              QString fileName = QString("%1_%2_to_%3_%4.txt")
                                .arg(prefix)
                                .arg(start)
                                .arg(end)
                                .arg(timeString);
              
              // 創建文件對象
              QFile file(fileName);
              
              // 以寫入模式打開文件
              if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                  qDebug() << "無法創建文件:" << fileName;
                  return false;
              }
              
              // 創建文本流
              QTextStream out(&file);
              
              // 寫入指定范圍的數字
              int count = 0;
              for (int i = start; i <= end; ++i) {
                  out << i;
                  count++;
                  
                  // 每10個數字換行
                  if (count % 10 == 0 || i == end) {
                      out << "\n";
                  } else {
                      out << " "; // 數字之間用空格分隔
                  }
              }
              
              // 關閉文件
              file.close();
              
              qDebug() << "成功寫入文件:" << fileName;
              qDebug() << "文件路徑:" << QDir::currentPath() + "/" + fileName;
              qDebug() << "寫入數字范圍:" << start << "到" << end << ",共" << (end - start + 1) << "個數字";
              
              return true;
          }
          
          // 獲取當前工作目錄
          static QString getCurrentPath()
          {
              return QDir::currentPath();
          }
          
          // 檢查文件是否存在
          static bool fileExists(const QString& fileName)
          {
              QFile file(fileName);
              return file.exists();
          }
      };
      
      #endif // UTILITIES_H
      
      

      QThread

      使用QThread類來創建線程,是Qt中最簡單的一種多線程實現方式,不過一般不建議使用,因為它的功能比較有限。
      使用QThread的方式為:繼承QThread并重寫run()函數。
      ** ExportThread.h **

      #ifndef EXPORTTHREAD_H
      #define EXPORTTHREAD_H
      
      #include <QThread>
      #include <QDebug>
      #include "Utilities.h"
      
      class ExportThread : public QThread
      {
          Q_OBJECT
      
      public:
          explicit ExportThread(QObject *parent = nullptr);
          
          // 設置導出參數
          void setExportParams(int start = 1, int end = 10000, const QString& prefix = "numbers");
          
      protected:
          void run() override;
          
      signals:
          void exportStarted();
          void exportFinished(bool success, const QString& message);
          void progressUpdate(int current, int total);
          
      private:
          int m_start;
          int m_end;
          QString m_prefix;
      };
      
      #endif // EXPORTTHREAD_H
      

      ** ExportThread.cpp **

      #include "ExportThread.h"
      #include <QDateTime>
      #include <QDir>
      
      ExportThread::ExportThread(QObject *parent)
          : QThread(parent)
          , m_start(1)
          , m_end(10000)
          , m_prefix("numbers")
      {
      }
      
      void ExportThread::setExportParams(int start, int end, const QString& prefix)
      {
          m_start = start;
          m_end = end;
          m_prefix = prefix;
      }
      
      void ExportThread::run()
      {
          qDebug() << "導出線程開始運行...";
          emit exportStarted();
          
          try {
              bool success = Utilities::writeNumbersToFile(m_start, m_end, m_prefix);
              if (success) {
                  emit exportFinished(true, QString("文件導出成功!范圍:%1-%2").arg(m_start).arg(m_end));
              } else {
                  emit exportFinished(false, "文件導出失?。?);
              }
              qDebug() << "導出線程完成";
              
          } catch (const std::exception& e) {
              qDebug() << "導出過程中發生異常:" << e.what();
              emit exportFinished(false, QString("導出過程中發生異常: %1").arg(e.what()));
          }
      }
      

      使用方式:

      ExportThread *exportThread = new ExportThread(this);
      exportThread->setExportParams(1, 10000, "numbers");
      exportThread->start();
      

      QObject的moveToThread方法實現多線程

      QObject的moveToThread方法可以將一個QObject對象移動到指定的線程中,實現多線程。
      使用方式:

      QObject *obj = new QObject();
      QThread *thread = new QThread();
      obj->moveToThread(thread);
      thread->start();
      

      示例:
      ** FileExportWorker.h **

      #ifndef FILEEXPORTWORKER_H
      #define FILEEXPORTWORKER_H
      
      #include <QObject>
      #include "Utilities.h"
      
      class FileExportWorker : public QObject
      {
          Q_OBJECT
      public:
          explicit FileExportWorker(QObject *parent = nullptr);
          void exportNumbers(int start, int end, const QString& prefix);
      
      signals:
          void progressUpdated(int current, int total);
          void statusUpdated(const QString& status);
      
      public slots:
      };
      
      #endif // FILEEXPORTWORKER_H
      

      ** FileExportWorker.cpp **

      #include "FileExportWorker.h"
      #include <QFile>
      #include <QTextStream>
      #include <QDateTime>
      #include <QDir>
      #include <QDebug>
      #include <QThread>
      #include <QCoreApplication>
      
      FileExportWorker::FileExportWorker(QObject *parent)
          : QObject(parent)
          , m_start(1)
          , m_end(10000)
          , m_prefix("numbers")
          , m_shouldStop(false)
      {
      }
      
      void FileExportWorker::setExportParams(int start, int end, const QString& prefix)
      {
          m_start = start;
          m_end = end;
          m_prefix = prefix;
      }
      
      void FileExportWorker::doExport()
      {
          qDebug() << "Worker線程ID:" << QThread::currentThreadId();
          qDebug() << "開始導出任務...";
          
          m_shouldStop = false;
          emit exportStarted();
          emit statusUpdated("正在準備導出...");
          
          try {
              bool success = false;
              
              emit statusUpdated("使用自定義參數導出...");
              success = exportNumbersWithProgress();
              
              if (m_shouldStop) {
                  emit exportFinished(false, "導出已被用戶取消");
              } else if (success) {
                  emit exportFinished(true, QString("文件導出成功!范圍:%1-%2").arg(m_start).arg(m_end));
              } else {
                  emit exportFinished(false, "文件導出失??!");
              }
              
          } catch (const std::exception& e) {
              qDebug() << "導出過程中發生異常:" << e.what();
              emit exportFinished(false, QString("導出過程中發生異常: %1").arg(e.what()));
          }
          
          qDebug() << "導出任務完成";
      }
      
      void FileExportWorker::stopExport()
      {
          m_shouldStop = true;
          emit statusUpdated("正在停止導出...");
      }
      
      bool FileExportWorker::exportNumbersWithProgress()
      {
          // 獲取當前時間并格式化為文件名
          QDateTime currentTime = QDateTime::currentDateTime();
          QString timeString = currentTime.toString("yyyy-MM-dd_hh-mm-ss");
          QString fileName = QString("%1_%2_to_%3_%4.txt")
                            .arg(m_prefix)
                            .arg(m_start)
                            .arg(m_end)
                            .arg(timeString);
          
          // 創建文件對象
          QFile file(fileName);
          
          // 以寫入模式打開文件
          if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
              qDebug() << "無法創建文件:" << fileName;
              return false;
          }
          
          // 創建文本流
          QTextStream out(&file);
          
          int total = m_end - m_start + 1;
          int count = 0;
          
          // 寫入指定范圍的數字
          for (int i = m_start; i <= m_end; ++i) {
              if (m_shouldStop) {
                  file.close();
                  QFile::remove(fileName); // 刪除未完成的文件
                  return false;
              }
              
              out << i;
              count++;
              
              // 每10個數字換行
              if (count % 10 == 0 || i == m_end) {
                  out << "\n";
              } else {
                  out << " "; // 數字之間用空格分隔
              }
              
              // 每處理100個數字發送一次進度更新
              if (count % 100 == 0 || i == m_end) {
                  emit progressUpdated(count, total);
                  emit statusUpdated(QString("已處理 %1/%2 個數字").arg(count).arg(total));
                  // 讓出CPU時間,允許其他操作
                  QCoreApplication::processEvents();
              }
          }
          
          // 關閉文件
          file.close();
          
          qDebug() << "成功寫入文件:" << fileName;
          qDebug() << "文件路徑:" << QDir::currentPath() + "/" + fileName;
          qDebug() << "寫入數字范圍:" << m_start << "到" << m_end << ",共" << total << "個數字";
          
          return true;
      }
      

      QConcurrent實現多線程導出數據

      QConcurrent是Qt提供的一個并發編程框架,用于簡化多線程編程。它提供了一些方便的函數和類,用于在多個線程中執行任務。本示例通過QConcurrent實現導出任務,實現多線程導出數據。

      使用方式:

      QFuture<bool> future = QConcurrent::run(this, &FileExportWorker::exportNumbersWithProgress);
      

      示例:
      ** FileExportWorker.h **

      #ifndef CONCURRENTEXPORTER_H
      #define CONCURRENTEXPORTER_H
      
      #include <QObject>
      #include <QString>
      #include <QFuture>
      #include <QFutureWatcher>
      #include <QtConcurrent>
      #include "Utilities.h"
      
      class ConcurrentExporter : public QObject
      {
          Q_OBJECT
      
      public:
          explicit ConcurrentExporter(QObject *parent = nullptr);
          
          // 開始導出任務
          void startExport(int start = 1, int end = 10000, const QString& prefix = "concurrent");
          
          // 取消導出任務
          void cancelExport();
          
          // 檢查是否正在運行
          bool isRunning() const;
      
      signals:
          void exportStarted();
          void exportFinished(bool success, const QString& message);
      
      private slots:
          void onExportFinished();
      
      private:
          QFutureWatcher<bool> *m_watcher;
          QFuture<bool> m_future;
          int m_start;
          int m_end;
          QString m_prefix;
      };
      
      #endif // CONCURRENTEXPORTER_H
      
      

      ** FileExportWorker.cpp **

      #include "ConcurrentExporter.h"
      #include <QFile>
      #include <QTextStream>
      #include <QDateTime>
      #include <QDir>
      #include <QDebug>
      #include <QThread>
      #include <QCoreApplication>
      #include <QtConcurrent/QtConcurrentRun>
      
      ConcurrentExporter::ConcurrentExporter(QObject *parent)
          : QObject(parent)
          , m_watcher(new QFutureWatcher<bool>(this))
          , m_start(1)
          , m_end(10000)
          , m_prefix("concurrent")
      {
          // 連接QFutureWatcher的信號
          connect(m_watcher, &QFutureWatcher<bool>::finished, this, &ConcurrentExporter::onExportFinished);
      }
      
      void ConcurrentExporter::startExport(int start, int end, const QString& prefix)
      {
          if (isRunning()) {
              qDebug() << "導出任務已在運行中";
              return;
          }
          
          m_start = start;
          m_end = end;
          m_prefix = prefix;
          
          qDebug() << "使用Qt Concurrent開始導出任務...";
          qDebug() << "當前線程ID:" << QThread::currentThreadId();
          
          emit exportStarted();
          
          m_future = QtConcurrent::run([=]() {
              qDebug() << "工作線程ID:" << QThread::currentThreadId();
              return Utilities::writeNumbersToFile(start, end, prefix);
          });
          // 設置QFutureWatcher監視QFuture
          m_watcher->setFuture(m_future);
      }
      
      void ConcurrentExporter::cancelExport()
      {
          if (isRunning()) {
              m_future.cancel();
          }
      }
      
      bool ConcurrentExporter::isRunning() const
      {
          return m_future.isRunning();
      }
      
      void ConcurrentExporter::onExportFinished()
      {
          bool success = false;
          QString message;
          
          if (m_future.isCanceled()) {
              message = "導出任務已被取消";
          } else {
              try {
                  success = m_future.result();
                  if (success) {
                      message = QString("文件導出成功!范圍:%1-%2").arg(m_start).arg(m_end);
                  } else {
                      message = "文件導出失??!";
                  }
              } catch (const std::exception& e) {
                  message = QString("導出過程中發生異常: %1").arg(e.what());
              }
          }
          
          emit exportFinished(success, message);
          qDebug() << "Qt Concurrent導出任務完成:" << message;
      }
      

      QRunnable結合QThreadPool方法實現多線程導出數據

      QRunnable是Qt提供的一個接口,用于在多線程中執行任務。QThreadPool是一個線程池,用于管理多個線程。本示例通過QRunnable接口實現導出任務,通過QThreadPool線程池管理線程,實現多線程導出數據。

      使用方式:

      QThreadPool *pool = QThreadPool::globalInstance();
      RunnableExportTask *task = new RunnableExportTask(1, 10000, "numbers");
      pool->start(task);
      

      示例:
      ** RunnableExportTask.h **

      #ifndef RUNNABLEEXPORTTASK_H
      #define RUNNABLEEXPORTTASK_H
      
      #include <QRunnable>
      #include <QObject>
      #include <QString>
      #include <QDebug>
      #include "Utilities.h"
      
      // 由于QRunnable不繼承QObject,我們需要一個信號發射器
      class ExportTaskNotifier : public QObject
      {
          Q_OBJECT
      
      public:
          explicit ExportTaskNotifier(QObject *parent = nullptr) : QObject(parent) {}
          
          void emitStarted() { emit exportStarted(); }
          void emitFinished(bool success, const QString& message) { emit exportFinished(success, message); }
          void emitProgress(const QString& status) { emit progressUpdated(status); }
      
      signals:
          void exportStarted();
          void exportFinished(bool success, const QString& message);
          void progressUpdated(const QString& status);
      };
      
      class RunnableExportTask : public QRunnable
      {
      public:
          explicit RunnableExportTask(int start = 1, int end = 10000, const QString& prefix = "runnable");
          
          // 設置通知器,用于發送信號
          void setNotifier(ExportTaskNotifier *notifier);
          
          // 設置導出參數
          void setExportParams(int start, int end, const QString& prefix);
          
          // QRunnable接口實現
          void run() override;
          
      private:
          int m_start;
          int m_end;
          QString m_prefix;
          ExportTaskNotifier *m_notifier;
      };
      
      #endif // RUNNABLEEXPORTTASK_H
      

      RunnableExportTask.cpp

      #include "RunnableExportTask.h"
      #include <QThread>
      #include <QDebug>
      
      RunnableExportTask::RunnableExportTask(int start, int end, const QString& prefix)
          : m_start(start)
          , m_end(end)
          , m_prefix(prefix)
          , m_notifier(nullptr)
      {
          // 設置任務完成后自動刪除
          setAutoDelete(true);
      }
      
      void RunnableExportTask::setNotifier(ExportTaskNotifier *notifier)
      {
          m_notifier = notifier;
      }
      
      void RunnableExportTask::setExportParams(int start, int end, const QString& prefix)
      {
          m_start = start;
          m_end = end;
          m_prefix = prefix;
      }
      
      void RunnableExportTask::run()
      {
          qDebug() << "QRunnable任務開始運行...";
          qDebug() << "當前線程ID:" << QThread::currentThreadId();
          
          if (m_notifier) {
              m_notifier->emitStarted();
              m_notifier->emitProgress("QRunnable任務:正在準備導出...");
          }
          
          try {
              if (m_notifier) {
                  m_notifier->emitProgress("QRunnable任務:開始寫入文件...");
              }
              
              bool success = Utilities::writeNumbersToFile(m_start, m_end, m_prefix);
              
              if (success) {
                  QString message = QString("文件導出成功!范圍:%1-%2").arg(m_start).arg(m_end);
                  if (m_notifier) {
                      m_notifier->emitProgress("QRunnable任務:導出完成");
                      m_notifier->emitFinished(true, message);
                  }
                  qDebug() << "QRunnable任務完成:" << message;
              } else {
                  QString message = "文件導出失敗!";
                  if (m_notifier) {
                      m_notifier->emitFinished(false, message);
                  }
                  qDebug() << "QRunnable任務失敗:" << message;
              }
              
          } catch (const std::exception& e) {
              QString message = QString("導出過程中發生異常: %1").arg(e.what());
              qDebug() << "QRunnable任務異常:" << message;
              if (m_notifier) {
                  m_notifier->emitFinished(false, message);
              }
          }
          
          qDebug() << "QRunnable任務結束";
      }
      
      posted @ 2025-08-06 10:02  來一碗糖醋錦鯉  閱讀(695)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 日韩全网av在线| 亚洲国产日韩a在线亚洲| 亚洲男人第一无码av网站| 日本污视频在线观看| 草草浮力影院| 国产午夜亚洲精品国产成人| 日韩 一区二区在线观看| aaa少妇高潮大片免费看| 果冻传媒18禁免费视频| 国产一区二区三区色噜噜| 香蕉乱码成人久久天堂爱| 国产精品美女自慰喷水| 麻豆国产va免费精品高清在线| 国产激情一区二区三区四区| 国产精品中文字幕一二三| 久久99精品久久久久麻豆| 国产中文字幕在线一区| 久久a级片| 亚洲色欲色欲www在线看| 少妇又爽又刺激视频| 亚洲精品欧美综合二区| 亚洲天堂在线观看完整版| 男人用嘴添女人下身免费视频| 亚亚洲视频一区二区三区| 极品尤物被啪到呻吟喷水| 成人欧美一区二区三区在线观看| 亚洲欧美日韩高清一区二区三区 | 国产精品熟女乱色一区二区| 亚洲精品揄拍自拍首页一| 日本亚洲一区二区精品| 亚洲国产精品久久久天堂麻豆宅男| 一区二区和激情视频| 人妻少妇偷人无码视频| 视频一区视频二区视频三| 四虎国产精品成人| 杨浦区| 高清中文字幕国产精品| 中文字幕理伦午夜福利片| 久久精品国产亚洲夜色av网站| 久久综合婷婷成人网站| 少妇xxxxx性开放|