Tôi có một đối tượng trực tiếp được triển khai theo cách sau. Nó được sử dụng để thực hiện các tác vụ dài trong nền. Chuỗi chính gọi các tác vụ bằng cách gửi tín hiệu đến các vị trí công cộng (ví dụ: doTask). Đây là một ví dụ bị tước bỏ (không được kiểm tra).Gọi phương thức khe mà không cần kết nối?
class MyTask : public QObject
{
Q_OBJECT
public:
MyTask();
~MyTask();
public slots:
void doTask(int param);
private slots:
void stated();
signals:
void taskCompleted(int result);
private:
QThread m_thread;
};
MyTask::MyTask()
{
moveToThread(&m_thread);
connect(&m_thread, SIGNAL(started()), this, SLOT(started()));
m_thread.start();
}
MyTask::~MyTask()
{
// Gracefull thread termination (queued in exec loop)
if(m_thread.isRunning())
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::started()
{
// initialize live object
}
void MyTask::doTask(int param)
{
sleep(10);
emit taskCompleted(param*2);
}
(cần) này hoạt động như mong đợi miễn là doTask() được gọi bởi tín hiệu. Nhưng nếu thread chính gọi doTask() trực tiếp thì nó sẽ được thực hiện bởi luồng chính. Đối với một số tác vụ, tôi muốn thực thi thực thi theo chuỗi của đối tượng trực tiếp, ngay cả khi phương thức khe được gọi trực tiếp.
Tôi có thể thêm mã trước mặt doTask() để kiểm tra xem chuỗi hiện tại có m_thread trong trường hợp nó thực hiện phương thức hay không. Nếu không, tôi muốn rằng doTask() phát ra một tín hiệu đến 'this' để một lệnh gọi doTask() được xếp hàng đợi trong vòng lặp m_thread exec và được thực hiện bởi nó càng sớm càng tốt.
Tôi có thể làm như thế nào?
EDIT: Dựa trên câu trả lời được đề xuất, đây là mã mới. Phương thức doTask bây giờ ủy quyền thực hiện bởi luồng của objet trực tiếp, ngay cả khi được gọi trực tiếp bởi luồng chính. Được gọi bằng tín hiệu vẫn hoạt động như mong đợi.
class MyTask : public QObject
{
Q_OBJECT
public:
explicit MyTask(QObject *parent = 0);
~MyTask();
public slots:
void doTask(int param);
private slots:
void doTaskImpl(int param);
signals:
void taskCompleted(int result);
private:
QThread m_thread;
};
MyTask::MyTask(QObject *parent) : QObject(parent)
{
moveToThread(&m_thread);
m_thread.start();
}
MyTask::~MyTask()
{
// Gracefull thread termination (queued in exec loop)
if(m_thread.isRunning())
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::doTask(int param)
{
QMetaObject::invokeMethod(this, "doTaskImpl", Q_ARG(int, param));
}
void MyTask::doTaskImpl(int param)
{
// Do the live oject's asynchronous task
sleep(10);
emit taskCompleted(param*2);
}
Đây là triển khai đơn giản nhất mà tôi có thể tìm thấy để hỗ trợ thực thi phương thức không đồng bộ trong một chuỗi riêng biệt. Các invocations của các phương thức doTask() sẽ được xếp hàng đợi và xử lý ngay sau khi thread được bắt đầu. Khi được gọi từ chuỗi đối tượng, nó sẽ được thực thi ngay lập tức (không được xếp hàng đợi).
Lưu ý rằng tín hiệu start() chỉ được phát ra khi bắt đầu luồng. Điều này có nghĩa là doTask() gọi phương thức được xếp hàng đợi trước khi luồng được bắt đầu sẽ thực thi trước khi khe phương thức started() được gọi. Đây là lý do tôi gỡ bỏ nó từ việc thực hiện ban đầu. Do đó, khởi tạo đối tượng tốt hơn nên được thực hiện trong hàm tạo.
tôi thấy một vấn đề ở đây: các tài liệu nói rằng bạn không thể di chuyển một đối tượng đến một thread nếu nó có một phụ huynh. Mã của bạn có hoạt động nếu MyTask được tạo với cha/mẹ không? – andref
Một câu hỏi tương tự cũng đã được trả lời trong [QT + Cách gọi khe từ mã C++ tùy chỉnh đang chạy trong một luồng khác] (http: // stackoverflow.com/questions/1144240/qt-how-to-call-slot-từ-custom-c-code-running-in-a-chuỗi khác). – Trilarion