Connecting signals/slots on separate thread using QtConcurrent::run

谁说我不能喝 提交于 2019-12-05 06:02:43

问题


In my application I have the following code in a dialog:

connect(drive, SIGNAL(FileProgressChanged(Progress)), SLOT(OnFileProgressChanged(Progress)));

QtConcurrent::run(this, &ProgressDialog::PerformOperation, Operation, *Path, OutPath, drive);

The PerformOperation function eventually calls to a function in drive which emits the signal FileProgressChanged, and my OnFileProgressChanged function is as follows:

void ProgressDialog::OnFileProgressChanged(Progress p)
{
    if (ui->progressCurrent->maximum() != p.Maximium)
        ui->progressCurrent->setMaximum(p.Maximium);

    ui->progressCurrent->setValue(p.Current);

    if (ui->groupBoxCurrent->title().toStdString() != p.FilePath)
        ui->groupBoxCurrent->setTitle(QString::fromStdString(p.FilePath));
}

I was doing some reading and saw that QFuture and QFutureWatcher support monitoring progress values (which would work great in this situation!), but those cannot be used in conjunction with QtConcurrent::run.

How would I go about connecting the signal that gets moved emitted on the separate thread to the slot on my main thread so I can monitor the progress of the function called on the emitter thread?

*Edit -- * I actually found an error with my code, but it doesn't seem to have an affect. I forgot to add this as an argument after the signal

connect(drive, SIGNAL(FileProgressChanged(Progress)), this, SLOT(OnFileProgressChanged(Progress)));

回答1:


Try using connect() with QueuedConnection, like:

connect(drive, SIGNAL(FileProgressChanged(Progress)), this, SLOT(OnFileProgressChanged(Progress)), Qt::QueuedConnection);

The connection should already be queued by default (since the emitter and receiver are in different threads), but this just makes it more explicit.

EDIT: The problem was that the Progress type wasn't registered with Qt's meta-object system. Adding qRegisterMetaType<Progress>("Progress"); fixed the problem.




回答2:


It appears as though the problem isn't with the cross-thread signal/slot, but instead with the parameter Progress. This question's answer goes into further detail, but the solution was found by doing the following in the header file in which Progress was declared:

struct Progress
{
    int Current;
    int Maximium;
    std::string FilePath;
    std::string FolderPath;
    int TotalMinimum;
    int TotalMaximum;
};

Q_DECLARE_METATYPE(Progress)

And in my form class:

qRegisterMetaType<Progress>();
    connect(Drive, SIGNAL(FileProgressChanged(const Progress&)), this, SLOT(OnFileProgressChanged(const Progress&)), Qt::QueuedConnection);

Changing Progress to const Progress& most likely isn't needed but I left it while testing.



来源:https://stackoverflow.com/questions/9367582/connecting-signals-slots-on-separate-thread-using-qtconcurrentrun

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!