Fix threading issues

This commit is contained in:
Nova 2025-10-22 03:22:24 +03:30
parent 16d951eed1
commit 546b023dbc
4 changed files with 63 additions and 11 deletions

View File

@ -167,11 +167,11 @@ void ActivateWindow(QWidget *w);
// //
void runOnUiThread(const std::function<void()> &callback); void runOnUiThread(const std::function<void()> &callback, bool wait = false);
void runOnNewThread(const std::function<void()> &callback); void runOnNewThread(const std::function<void()> &callback, bool wait = false);
void runOnThread(const std::function<void()> &callback, QObject *parent); void runOnThread(const std::function<void()> &callback, QObject *parent, bool wait = false);
template<typename EMITTER, typename SIGNAL, typename RECEIVER, typename ReceiverFunc> template<typename EMITTER, typename SIGNAL, typename RECEIVER, typename ReceiverFunc>
inline void connectOnce(EMITTER *emitter, SIGNAL signal, RECEIVER *receiver, ReceiverFunc f, inline void connectOnce(EMITTER *emitter, SIGNAL signal, RECEIVER *receiver, ReceiverFunc f,

View File

@ -249,38 +249,84 @@ void ActivateWindow(QWidget *w) {
w->activateWindow(); w->activateWindow();
} }
void runOnUiThread(const std::function<void()> &callback) { void runOnUiThread(const std::function<void()> &callback, bool wait) {
// any thread // any thread
auto *timer = new QTimer(); auto *timer = new QTimer();
auto thread = mainwindow->thread(); auto thread = mainwindow->thread();
timer->moveToThread(thread); timer->moveToThread(thread);
timer->setSingleShot(true); timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() {
QEventLoop loop;
QObject::connect(timer, &QTimer::timeout, [=, &loop]() {
// main thread // main thread
callback(); callback();
timer->deleteLater(); timer->deleteLater();
if (wait)
{
QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
}
}); });
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
if (wait && QThread::currentThread() != thread) {
loop.exec();
}
} }
void runOnNewThread(const std::function<void()> &callback) { void runOnNewThread(const std::function<void()> &callback, bool wait) {
createQThread(callback)->start(); auto *timer = new QTimer();
auto thread = new QThread();
timer->moveToThread(thread);
timer->setSingleShot(true);
thread->start();
QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);
QEventLoop loop;
QObject::connect(timer, &QTimer::timeout, [=, &loop]() {
callback();
timer->deleteLater();
QMetaObject::invokeMethod(thread, "quit", Qt::QueuedConnection);
if (wait)
{
QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
}
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
if (wait && QThread::currentThread() != thread) {
loop.exec();
}
} }
void runOnThread(const std::function<void()> &callback, QObject *parent) { void runOnThread(const std::function<void()> &callback, QObject *parent, bool wait) {
auto *timer = new QTimer(); auto *timer = new QTimer();
auto thread = dynamic_cast<QThread *>(parent); auto thread = dynamic_cast<QThread *>(parent);
if (thread == nullptr) { if (thread == nullptr) {
timer->moveToThread(parent->thread()); timer->moveToThread(parent->thread());
thread = parent->thread();
} else { } else {
timer->moveToThread(thread); timer->moveToThread(thread);
} }
timer->setSingleShot(true); timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() {
QEventLoop loop;
QObject::connect(timer, &QTimer::timeout, [=, &loop]() {
callback(); callback();
timer->deleteLater(); timer->deleteLater();
if (wait)
{
QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
}
}); });
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0)); QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
if (wait && QThread::currentThread() != thread) {
loop.exec();
}
} }
void setTimeout(const std::function<void()> &callback, QObject *obj, int timeout) { void setTimeout(const std::function<void()> &callback, QObject *obj, int timeout) {

View File

@ -62,7 +62,10 @@ namespace Configs_sys {
if (restarting) return; if (restarting) return;
MW_show_log("[Fatal] " + QObject::tr("Core exited, cleaning up...")); MW_show_log("[Fatal] " + QObject::tr("Core exited, cleaning up..."));
GetMainWindow()->profile_stop(true, true); runOnUiThread([=, this]
{
GetMainWindow()->profile_stop(true, true);
}, true);
// Retry rate limit // Retry rate limit
if (coreRestartTimer.isValid()) { if (coreRestartTimer.isValid()) {

View File

@ -570,7 +570,10 @@ void MainWindow::profile_start(int _id) {
runOnNewThread([=, this] { runOnNewThread([=, this] {
// stop current running // stop current running
if (running != nullptr) { if (running != nullptr) {
profile_stop(false, true, true); runOnUiThread([=, this]
{
profile_stop(false, true, true);
}, true);
} }
// do start // do start
MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->bean->DisplayTypeAndName())); MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->bean->DisplayTypeAndName()));