久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

如何在 WINAPI 線程中更改 Qt 小部件?

How to alter Qt Widgets in WINAPI threads?(如何在 WINAPI 線程中更改 Qt 小部件?)
本文介紹了如何在 WINAPI 線程中更改 Qt 小部件?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我需要在三個 WINAPI 線程中同時更改三個進度條.由于我的功能,進度條的更改值是可以訪問這些條的,因此它們是 MainWindow 類的成員.所以我創建了帶有 CreateThread 函數所需簽名的包裝器,但是當我嘗試啟動我的線程時,我仍然遇到分段錯誤.它可能是由什么引起的以及如何處理它并使我的代碼正常工作?

我的函數示例:

DWORD MainWindow::ThreadFunc1(){for(int i = 0; i <100; i++){ui->progressBar->setValue(i);睡眠(500);}返回0;}

我的包裝器示例

DWORD WINAPI MainWindow::threadStart1(LPVOID lpParams){MainWindow* This = (MainWindow*) lpParams;return This->ThreadFunc1();}

解決方案

我不知道 OP 已經問過一個非常相似的問題

I need to alter three progress bars simultaneously in three WINAPI threads. Since my funtions, that change value of progress bars are to have access to these bars, they are members of MainWindow class. So i created wrappers with signature that is required by CreateThread function, but I still get segmentation fault when I try to start my threads. What it can be caused by and how to handle this and get my code to work?

Example of my function:

DWORD MainWindow::ThreadFunc1()
{
    for(int i = 0; i < 100; i++)
        {
            ui->progressBar->setValue(i);
            sleep(500);
        }
    return 0;
}

Example of my wrapper

DWORD WINAPI MainWindow::threadStart1(LPVOID lpParams)
{
    MainWindow* This = (MainWindow*) lpParams;
    return This->ThreadFunc1();
}

解決方案

I was not aware that OP already asked a very similar question

SO: Problem with using WINAPI threads in Qt in C++

which has (at the time of this writing) already two valuable answers.

Nevertheless, I publish my sample which I had complete before noticing the above.


Multi-threading usually requires additional care for the interthread communication. In opposition to multi-processing (where each process has unshared variables by default and requires special effort for Inter-Process Communication), all threads may access the same process variables. As long as each thread uses its variables exclusively during its life-time, everything is fine. As soon as at least one thread reads a variable which is modified by another thread, the trouble starts. To prevent data races and race-conditions, a thread synchronization is needed for which the human author is responsible. Ignoring this (even unintendedly) introduces Undefined Behavior, and, in such cases, the compiler doesn't contribute any helpful diagnosis for this.

The Qt GUI is not intended for multi-threading. Hence, the widgets and widget properties are not thread-safe.

Beside of this, Qt is prepared for multi-threading.

  1. QObject is prepared to have a thread affinity. → Thread Affinity

  2. Qt signals can be used for interthread communication. For this, all relevant flavors of QObject::connect() provide a parameter of Qt::ConnectionType. When a Qt signal is connected to a slot of another QObject, by default, the thread affinities of sender and receiver object will be used to adjust the connection type appropriately:

    If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

  3. If a non-GUI thread calls member functions of GUI objects, this results surely in Undefined Behavior (due to the lack of thread-safety). Instead, the thread may add a request to the event loop of the GUI thread so that the GUI thread can process it in order and sync. For this, QApplication::postEvent() can be used. Apparently, this is one of the rare Qt GUI functions which is explicitly remarked as thread-safe.

A more encompassing overview is given in Thread Support in Qt

  1. Another option is the usage of the std:: C++ multi-threading tools like std::thread to spawn and join threads, std::mutex (and company) to guard shared accesses, and/or std::atomic for a (potentially) lock-free interthread communication.

This has the advantage that (maybe already existing) thread-safe code can be used which is based on std:: C++ library stuff exclusively. The (periodical) update of Qt GUI is managed by a QTimer which is some kind of polling but results in a simple refresh-rate management without the danger that other threads start to flood the event loop of the GUI thread. (Updating the Qt GUI too frequently may result in a considerable performance impact with a noticable drop of its reactivity.)

About option 4, I once wrote an answer SO: Qt C++ Displaying images outside the GUI thread (Boost thread) for yet another similar question.

Recalling this, I wrote a new sample for the question of OP:

The C++ source testQProgressMultiThreading.cc:

// standard C++ header:
#include <atomic>
#include <chrono>
#include <thread>

// Qt header:
#include <QtWidgets>

// a wrapper for a thread with some added context
struct Worker {
  const uint id; // constant over thread runtime - no sync. needed
  std::thread thread; // the thread instance
  std::atomic<uint> progress; // shared data (written in worker, read by UI)
  std::atomic<bool> exit; // flag to signal abort (from UI to worker)

  Worker(uint id): id(id), progress(0), exit(true) { }
  ~Worker() { if (thread.joinable()) thread.join(); }

  void start()
  {
    if (thread.joinable()) return; // worker already working
    qDebug() << "Start worker " << id;
    progress = 0; exit = false;
    thread = std::thread(&Worker::work, this);
  }

  void stop()
  {
    if (!thread.joinable()) return; // worker not working
    exit = true;
    thread.join();
    progress = 0;
    qDebug() << "Worker" << id << "finished.";
  }

  void work()
  {
    qDebug() << "Enter worker " << id;
    while (progress < 100 && !exit) {
      // consume some time (without heating the CPU too much)
      std::this_thread::sleep_for(std::chrono::milliseconds(50));
      // confirm some work progress
      ++progress;
    }
    qDebug() << "Leaving worker " << id;
  }

  bool working() const { return thread.joinable(); }
};

// main application
int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // workers
  Worker worker1(1), worker2(2), worker3(3);
  // setup GUI
  QWidget qWinMain;
  qWinMain.setWindowTitle("Test QProgress Multi-Threading");
  qWinMain.resize(640, 480);
  QVBoxLayout qVBox;
  QHBoxLayout qHBox;
  qHBox.addStretch();
  QPushButton qBtnStart1("Start 1");
  qHBox.addWidget(&qBtnStart1);
  QPushButton qBtnStart2("Start 2");
  qHBox.addWidget(&qBtnStart2);
  QPushButton qBtnStart3("Start 3");
  qHBox.addWidget(&qBtnStart3);
  QPushButton qBtnStop("Stop");
  qHBox.addWidget(&qBtnStop);
  qVBox.addLayout(&qHBox);
  QProgressBar qProgress1;
  qVBox.addWidget(&qProgress1);
  QProgressBar qProgress2;
  qVBox.addWidget(&qProgress2);
  QProgressBar qProgress3;
  qVBox.addWidget(&qProgress3);
  qWinMain.setLayout(&qVBox);
  qWinMain.show();
  // prepare timer
  QTimer qTimerProgress;
  qTimerProgress.setInterval(50); // update rate for GUI 50 ms -> 20 Hz (round about)
  // install signal-handlers
  QObject::connect(&qBtnStart1, &QPushButton::clicked,
    [&](bool) {
      worker1.start();
      if (!qTimerProgress.isActive()) qTimerProgress.start();
    });
  QObject::connect(&qBtnStart2, &QPushButton::clicked,
    [&](bool) {
      worker2.start();
      if (!qTimerProgress.isActive()) qTimerProgress.start();
    });
  QObject::connect(&qBtnStart3, &QPushButton::clicked,
    [&](bool) {
      worker3.start();
      if (!qTimerProgress.isActive()) qTimerProgress.start();
    });
  QObject::connect(&qBtnStop, &QPushButton::clicked,
    [&](bool) {
      worker1.stop(); qProgress1.setValue(worker1.progress);
      worker2.stop(); qProgress2.setValue(worker2.progress);
      worker3.stop(); qProgress3.setValue(worker3.progress);
      qTimerProgress.stop();
    });
  QObject::connect(&qTimerProgress, &QTimer::timeout,
    [&](){
      qProgress1.setValue(worker1.progress);
      if (worker1.progress >= 100) worker1.stop();
      qProgress2.setValue(worker2.progress);
      if (worker2.progress >= 100) worker2.stop();
      qProgress3.setValue(worker3.progress);
      if (worker3.progress >= 100) worker3.stop();
      if (!worker1.working() && !worker2.working() && !worker3.working()) {
        qTimerProgress.stop();
      }
    });
  // runtime loop
  return app.exec();
}

A CMake build-script CMakeLists.txt to prepare a VS solution:

project(QProgressMultiThreading)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Qt5Widgets CONFIG REQUIRED)

include_directories("${CMAKE_SOURCE_DIR}")

add_executable(testQProgressMultiThreading testQProgressMultiThreading.cc)

target_link_libraries(testQProgressMultiThreading Qt5::Widgets)

Built and tested in VS2017 (Windows 10, Qt 5.13):

這篇關于如何在 WINAPI 線程中更改 Qt 小部件?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 亚洲一区二区免费 | 日韩福利视频 | 美女福利视频 | 亚洲一区二区三区视频 | 国产一区二区三区精品视频 | 色在线视频 | 午夜网站在线观看 | 视频在线一区 | 91手机看片| 国产成人在线免费观看 | av每日更新 | 在线观看视频一区 | 国产乱码一区二区三区 | 一区二区三区免费 | 成人不卡| 午夜视频在线看 | 日韩国产精品视频 | 亚洲第一色 | 欧美精品在线播放 | 激情小说在线视频 | 六月色 | 欧美1级片 | 日韩高清一区二区 | 国产一级网站 | 国产逼逼 | 日本美女一级片 | 午夜视频免费在线观看 | 手机av在线免费观看 | 四虎影院www | 曰韩一级片 | 最新日韩av | 欧美日韩国 | 久久一区二区视频 | 久久综合亚洲 | 中文字幕在线观看日本 | 国产黄色在线播放 | 免费视频a| 国产精品爽爽爽 | 亚洲国产日韩在线 | 欧美理论片在线观看 | 91久久国产综合久久 |