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>
inline void connectOnce(EMITTER *emitter, SIGNAL signal, RECEIVER *receiver, ReceiverFunc f,

View File

@ -249,38 +249,84 @@ void ActivateWindow(QWidget *w) {
w->activateWindow();
}
void runOnUiThread(const std::function<void()> &callback) {
void runOnUiThread(const std::function<void()> &callback, bool wait) {
// any thread
auto *timer = new QTimer();
auto thread = mainwindow->thread();
timer->moveToThread(thread);
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() {
QEventLoop loop;
QObject::connect(timer, &QTimer::timeout, [=, &loop]() {
// main thread
callback();
timer->deleteLater();
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 runOnNewThread(const std::function<void()> &callback) {
createQThread(callback)->start();
void runOnNewThread(const std::function<void()> &callback, bool wait) {
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 thread = dynamic_cast<QThread *>(parent);
if (thread == nullptr) {
timer->moveToThread(parent->thread());
thread = parent->thread();
} else {
timer->moveToThread(thread);
}
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() {
QEventLoop loop;
QObject::connect(timer, &QTimer::timeout, [=, &loop]() {
callback();
timer->deleteLater();
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 setTimeout(const std::function<void()> &callback, QObject *obj, int timeout) {

View File

@ -62,7 +62,10 @@ namespace Configs_sys {
if (restarting) return;
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
if (coreRestartTimer.isValid()) {

View File

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