Многопоточность: получилось (12.07.2024). |
![]() |
2024 - Июль | |||
12.07.2024 17:20 | |||
Между тем, хочу напрогать приблуду - лютую и конфиденциальную. И, с учётом того, что дома теперь частоты ниже, а потоков 24, - пришлось сделать ещё попытку. Удалось реализовать - только на Qt v.5.15.2 в среде Astra Linux SE v.1.7.4.0 (7). Сначала всё было то же самое: ни один из примеров к более новым версиям Qt не работал. Например, отсутствуют QThread::create или bind; или connect не компилируется, или класс не создаётся, или метод run в QtConcurrentRun на фиг посылает. В итоге, примеры были выкинуты в мусорку - и стал делать по логике и с отключенным мозгом (в надежде, что в алогичной и враждебной среде Qt хотя бы с этим механизмом багов нет). Ага, щазз. Сначала был создан простейший класс, именно в mainwindow.h: с некоторым набором функций, раскидываемых по разным потокам и работающих по-разному - с целью более детального тестирования. class Thread_Functions : public QObject { Q_OBJECT public slots: void vPrint_Lesha_30sec(void); void vPrint_Nubas_60sec(void); void vBurn_Core_30sec(void); void vBurn_Core_60sec(void); }; Уже надрочившись с примерами - сформировался список необходимых инклудов в CPP-файле. #include "qthread.h" #include "qdebug.h" #include "qdatetime.h" Функции нагрузки ядра были созданы для понимания, как работают потоки через загрузку процессора в диспетчере устройств. void Thread_Functions::vBurn_Core_30sec(void) { quint64 qui64Begin = QDateTime::currentMSecsSinceEpoch(); while (QDateTime::currentMSecsSinceEpoch()-qui64Begin < 30000) {} } Это дало результаты: - и объект класса с функциями, и объект потока - должны создаваться локально в месте старта потока. Глобальный объект потока портится после отработки, глобальный объект функций приводит к работе только одного потока за раз; - moveToThread по-прежнему недостаточно, чтобы засунуть объект с функциями в поток так, чтобы он работал; - удалось сформировать удачный connect, в интернете не описываемый. Простой до безобразия - но отсутствующий в примерах, и обязательно со словами "SIGNAL" и "SLOT" в строке - безо всяких амперсандов, скобок, точек, стрелок и прочей фигни; - диспетчер задач показывает, что поток не убивается после выполнения, несмотря на уничтожение самого объекта. Возможно, баг ОС, - но на работу не влияет; - чёткая цифра 8% процессора на ядро (опять баг ОС: 8.3(3) должно быть) позволяет чётко понимать, сколько потоков работает - перепроверка багов цифры о количестве потоков; - 12 кнопок для 12 потоков - успешно жгли процессор на 100% загрузки. Общее количество потоков при первом запуске 13, при втором - 25. Если нажимать на одну и ту же кнопку несколько раз - оказалось равнозначным нажатию на несколько разных. void MainWindow::on_pushButton_Nubas_clicked() { Thread_Functions *oThread_Functions = new Thread_Functions(); QThread *oThread = new QThread(); oThread_Functions->moveToThread(oThread); connect(oThread, SIGNAL(started()), oThread_Functions, SLOT(vPrint_Nubas_60sec())); //connect(oThread, SIGNAL(started()), oThread_Functions, SLOT(vBurn_Core_60sec())); oThread->start(); } Вывод сообщений в дебаг и стринглист показали: - не требуется использовать функции типа lock для разделения данных разных потоков друг от друга; - поток отрабатывает строго по времени - именно большой буфер продолжает выводиться в Вывод Приложения, даже после выхода из программы; - баг Qt: ни clear, ни delete, ни NULL - не удаляют QStringList до конца - в итоге, при многократном использовании, 32ГБ RAM быстро переполнились. void Thread_Functions::vPrint_Lesha_30sec(void) { quint64 qui64Begin = QDateTime::currentMSecsSinceEpoch(); QStringList *qslTexts = new QStringList; //while (QDateTime::currentMSecsSinceEpoch()-qui64Begin < 30000) qDebug() << "Lesha - "; while (QDateTime::currentMSecsSinceEpoch()-qui64Begin<30000 && qslTexts->count()<21460000) qslTexts->append("Lesha - "); for (int iCurrent_Position=0; iCurrent_Position<qslTexts->count(); iCurrent_Position++) { if (!qslTexts->at(iCurrent_Position).contains("Lesha - ")) qDebug() << "Ne Lesha!"; } qslTexts->clear(); delete qslTexts; qslTexts = NULL; int iStopper = 0; //Проверка времени вывода надписей: глючит не функция, а Qt. Огромный объём данных продолжает писаться в Вывод Приложения - даже если программа уже закрыта. } Так как в слоты нельзя передавать параметры - пока неясно, как сделать взаимодействие потока с UI. В полезных исходниках целиком проект выложен. (добавлено 13.07.2024) Да, похоже, 2015 год - граница корректности работы средств разработки с многопоточностью (в плане понятности и удобства использования разработчиком). В Visual Studio 2015 года показали реально работающую реализацию - ещё удобнее, чем в Qt: всего несколько строк, без всяких слотов, классов и прочей хрени - но с принудительным залочиванием каждого потока. (добавлено 04.08.2024) С Borland C++ Builder - всё получилось, попроще и пологичнее. |
|||
Обновлено ( 04.08.2024 04:37 ) |