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

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

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

問題描述

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

我的函數(shù)示例:

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 已經(jīng)問過一個(gè)非常相似的問題

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):

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

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

相關(guān)文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數(shù)據(jù)?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環(huán): for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環(huán)?)
Reusing thread in loop c++(在循環(huán) C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環(huán)形?)
主站蜘蛛池模板: 成人在线视频看看 | 国产特级毛片 | www.嫩草 | 99视频| 激情五月激情综合网 | 国产一区二区美女 | 亚洲精品在线免费 | 成人在线免费网站 | 久在线精品视频 | 国产精品网址 | 日韩精品一区二区三区免费视频 | 免费激情网站 | 91 久久| 久久精品国产亚洲 | 亚洲一区免费在线 | 欧美日韩精品一区二区天天拍 | 97福利在线 | 精品在线播放 | 国产亚洲精品一区二区三区 | 久久久久九九九女人毛片 | 国产96色在线 | 日本一区二区三区四区 | 欧美一区二区三区久久精品 | 亚洲人成人一区二区在线观看 | 国产中文字幕在线观看 | 无码一区二区三区视频 | 久久精品小视频 | 伊人久麻豆社区 | 成人高清在线 | 国产高清视频一区 | 中文字幕高清av | 色婷婷九月 | 男人的天堂久久 | 日韩精品一区二区三区中文字幕 | 色视频网站免费 | 欧美v免费 | 天天插天天狠天天透 | 美女久久| 亚洲欧洲视频 | 犬夜叉在线观看 | 久久中文免费视频 |