Hello everyone and again the question about multithreading, I post the source code of the test example. And immediately to the question, there is a calculation code that works in the stream, we can forcibly close it using the stop flag by pressing a button and at the end of the function send the emit finished () signal everything works. But when we in a stream function call the function that is defined in the dll that we perceive as a black box, that is, the stream accesses it, its arguments contain data and inside it are calculated, in the dll itself, how does it forcibly interrupt and delete a stream? there are no flags and signals about its interruption inside it, it works until it calculates. Counts inside a couple of minutes and we wait for the return value, and only on exiting it our stream is interrupted, and then it is deleted by our flag and the finished signal finished (). And again, so how to interrupt the forced flow? even if inside the dll function is still being calculated, without waiting for the return value? I spread a test working example for a reference point.

worker.cpp

#include "worker.h" #include <QDebug> Worker::Worker(QObject *parent) : QObject(parent) { Stop = false; temp = 0; } Worker::~Worker() { qDebug() << "destruction Thread"; } void Worker::process() { Stop = false; if(!Stop == true) { for (; temp <= 100000; temp++) { if(!Stop == true) { emit(sendNumber(temp)); qDebug() << temp; // ЗДЕСЬ БУДЕТ ВЫЗЫВАТСЯ ФУНКЦИЯ ИЗ DLL // в её аргументы будут поступать данные и внутри обрабатываться очень долго // до 2-3 минут обработки и возвращать значения // но нам нужно сразу ее прервать, даже если она еще внутри расчитывает } else { return; } } } emit finished(); // вызывается при завершении расчёта } void Worker::reciveBoolStop(bool Numb) { Stop = Numb; qDebug() << "reciveBoolStop = " << Stop; emit finished(); // вызывается при отмене расчёта } 

worker.h

 #ifndef WORKER_H #define WORKER_H #include <QObject> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = 0); ~Worker(); bool Stop; int temp; signals: void finished(); //void error(QString err); void sendNumber(int); public slots: void process(); void reciveBoolStop(bool Numb); }; #endif // WORKER_H 

mainwindow.cpp

 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #include <QtCore> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(this->ui->pushButton_start, SIGNAL(clicked()), this, SLOT(startGUI())); connect(this->ui->pushButton_stop, SIGNAL(clicked()), this, SLOT(stopGUI())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::startGUI() { // Создание потока QThread* thread = new QThread; Worker* worker = new Worker(); // Передаем права владения "рабочим" классом, классу QThread. worker->moveToThread(thread); // Соединяем сигнал started потока, со слотом process "рабочего" класса, т.е. начинается выполнение нужной работы. connect(thread, SIGNAL(started()), worker, SLOT(process())); // Отображаем в главном потоке Gui, значения из вторичного потока connect(worker, SIGNAL(sendNumber(int)), this, SLOT(LineEditUi(int))); // Оповещаем поток, что нужно остановиться connect(this, SIGNAL(sendNumberBoolStop(bool)), worker, SLOT(reciveBoolStop(bool)), Qt::DirectConnection); // ВЫЗЫВАЕТ УТЕЧКУ ПАМЯТИ //connect(worker, SIGNAL(finished()), thread, SLOT(quit())); // По завершению выходим из потока, и удаляем рабочий класс connect(worker, SIGNAL(destroyed(QObject*)), thread, SLOT(quit())); // ТАК ПРАВИЛЬНО connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); // Удаляем поток, после выполнения операции connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); } void MainWindow::LineEditUi(int number) { ui->lineEdit->setText(QString::number(number)); } void MainWindow::stopGUI() { Stop = true; qDebug() << Stop; sendNumberBoolStop(Stop); qDebug() << "sendMumberBoolStop = " << Stop; } 

mainwindow.h

 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "worker.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); bool Stop; public slots: void startGUI(); void stopGUI(); void LineEditUi(int number); signals: void sendNumberBoolStop(bool); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H 

main.cpp

 #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 

    1 answer 1

    The best solution is to upgrade the library itself so that it receives and understands signals from the control flow. Of course, if the source of this library is available. In the opposite case, when the execution context goes to the connected library, power over it is lost, and all that is possible to do is either abruptly pull up the leash using force, or wait patiently for him to return to the fold of caring control.

    The use of force by good ends rarely, but if the decision was made consciously and because of particularly urgent need , it is quite real.

    First, you need to allow QThread force and immediately end the thread it controls:

     QThread::setTerminationEnabled(bool enabled = true) 

    The second, oddly enough, directly the very end:

     QThread::terminate() 

    Note that the code that follows the execution context string in the QThread::run() method will not be executed after the terminate() call. For example:

     void QThread::run() { myFunc1(); // Контекст выполнения здесь. myFuncInDll(); // Если уничтожить поток, то всё, // что находится ниже выполнено не будет. myFunc2(); emit finished(); } 

    The class Worker according to the code in question is moved to a thread controlled by QThread . Besides the fact that everything that follows in Worker will not be executed, the release of the occupied resources will not happen either. Needless to say, the library itself can mess up, being connected to some external resource and recording data at the time of the emergency stop.

    If the reason for the immediate shutdown of a thread is such a reason as the fact that the user cannot wait, then hide the work process with an appropriate response in the graphical user interface.

    For example, if any button is designed to stop the flow, then let it show that everything has been successfully completed, while the flow hidden in this way will continue its work transparently and eventually complete it correctly.

    If the user wants to immediately exit the program, it is not necessary to obey him. You can simply close the window without completing the process itself, which will continue its work and also correctly complete it.