久久久久久久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 ()?環形?)
主站蜘蛛池模板: 欧美福利专区 | 成人av片在线观看 | 日韩中文一区 | 91传媒在线观看 | 日韩中出| 久久久青草 | 色999视频 | 四虎永久免费影院 | 成人午夜视频在线观看 | 国产精品18久久久 | 亚洲男人网 | 色综合久久久 | 狠狠操狠狠色 | 9191在线播放 | 黄色一级毛片免费看 | 精品国产一区二区三区久久久久久 | 国产日韩欧美 | 欧美激情一区二区三区 | 在线日韩| 国产一区二区影院 | 免费播放一级片 | 欧美日韩一区二区三区不卡视频 | 精品免费国产一区二区三区四区介绍 | 日产精品久久久一区二区福利 | 天堂av资源| 久久亚洲一区二区三区四区 | 欧美日韩中文在线 | 国产一区二区三区久久久久久久久 | 国产免费一级片 | 亚洲激情一区二区三区 | 久久精彩视频 | 99久久婷婷国产综合精品电影 | 免费视频二区 | 久久精品免费一区二区三 | 国产视频在线一区二区 | 一级无毛片| 在线免费看毛片 | 日韩av中文 | aaaaaaa片毛片免费观看 | 久久久久网站 | 欧美在线视频网站 |