C++ Qt线程有两个参数

C++ Qt线程有两个参数,c++,multithreading,qt,C++,Multithreading,Qt,我想使用QThread构建我的Qt应用程序,因为我想将长进程从主窗口分离到线程 我在这段代码中遇到了一个问题: class Worker : public QObject { Q_OBJECT public slots: void doWork(const std::string &param2, std::string &param2) { int result; /* ... here is the expensive or

我想使用QThread构建我的Qt应用程序,因为我想将长进程从主窗口分离到线程

我在这段代码中遇到了一个问题:

class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const std::string &param2, std::string &param2) {
        int result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }

signals:
    void resultReady(const int &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::input,&Controller::output, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const int &);
private:
    string input;
    string output;
};
我希望我的代码可以将两个值(输入、输出)字符串传输到QThread,并作为结果以int值的形式发出信号。但是,列出的代码不起作用。我正在寻找的解决方案看起来像.Net中的blackgroundWorker,并且具有类似的功能

我应该这样做吗

编辑

我不能编译这个。我得到一个错误:

Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'QMetaObject::Connection QObject::connect(const QObject *,const char *,const char *,Qt::ConnectionType) const': cannot convert argument 2 from 'std::string Controller::* ' to 'const char *'   GPCTool C:\repo\Tool\Controller.cpp 21  

首先,这行代码不起作用:

connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
workerThread
位于主线程中,而
worker
位于由
workerThread
处理(创建)的线程中。因此,当触发
QThread::finished
时,将异步调用
QObject::deleteLater
(请参见
Qt::AutoConnection
),但是如果线程已经完成,异步调用将永远不会完成

情况甚至变得更糟。即使调用了
QObject::deleteLater
,延迟删除也不会发生,原因相同:线程已经完成


此调用与
connect()
的任何原型都不匹配。无法将变量连接到插槽

创建一个中间信号:

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::callDoWork, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
        emit callDoWork(input, output);
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
signals:
    emit callDoWork(std::string, str::string);
public slots:
    void handleResults(const int &);
private:
    string input;
    string output;
};
或者使用
QMetaObject::invokeMethod()

请注意,要使这两个解决方案发挥作用,您需要使用Q_DECLARE_元类型和qRegisterMetaType注册
std::string
(请参阅)

您还希望将
std:string&output
替换为
std::string*output
,因为Qt将在两个线程之间复制
output
,并且您将看不到反映到原始
output
变量的更改


由于
resultedy
的签名与
handleResults
不匹配,因此无法编译此文件。要将信号连接到插槽,它们必须采用相同的参数

我建议你读一读



关于线程的使用,我认为您应该查看和

你可能读过一篇愚蠢的博客,声称必须创建一个worker对象并将其与普通线程一起使用,而不是简单地从
QThread
派生并实现
run()

因为您的工作负载仅仅是一个函数,只需要一次,所以这样做更容易


在这两种情况下,只要通过构造函数或setter方法将值传递给类,实际上不需要将它们作为参数传递给
doWork()

“不工作”到底是什么意思?它不编译吗?。它会崩溃吗?它会产生意外的结果吗?我得到了错误代码,我在EDITWell中写的,似乎你的第二个
connect
有太多参数,不是吗?这行看起来很奇怪:
connect(这,&Controller::input,&Controller::output,worker,&worker::doWork)您的代码不完整;特别是,它似乎缺少一个
main()
函数和至少一个
#include
,并且您还没有显示
Controller::input()
Controller::output()
的声明。请输入您的代码,使其成为您问题的一部分,然后我们可以尝试复制并解决它。您还应该阅读.connect(this,&Controller::input,&Controller::output,worker,&worker::doWork);在这一行中,我希望将输出和输入字符串作为参数传输到doWork方法。我已经更新了答案。您一定要花时间阅读Qt信号和插槽文档。谢谢您的回答。我使用第一种方式,我将阅读更多关于插槽和信号的内容:)。因为它声称是使用
QThread
的“方式”,所以它很愚蠢,因为没有单一方式。当工作程序正在执行基于事件循环的工作时,使用带有
moveToThread
的工作程序是一个不错的选择。如果工作人员运行的是单个函数或无止境的循环,那么这只是不必要的编码开销,这增加了必须处理两个对象而不是一个对象的复杂性。
class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::callDoWork, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
        emit callDoWork(input, output);
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
signals:
    emit callDoWork(std::string, str::string);
public slots:
    void handleResults(const int &);
private:
    string input;
    string output;
};
Controller() {
    Worker *worker = new Worker;
    worker->moveToThread(&workerThread);
    connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);

    connect(worker, &Worker::resultReady, this, &Controller::handleResults);
    workerThread.start();
    QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection, Q_ARG(std::string, input), Q_ARG(std::string, output));
}
connect(worker, &Worker::resultReady, this, &Controller::handleResults);