2009-12-28 44 views
5

Tôi đang cố chạy một phương thức trên luồng GUI bằng QMetaObject :: invokeMethod, trả về true. Nhưng, nếu tôi sử dụng Qt :: QueuedConnection phương pháp của tôi không bao giờ được gọi (ngay cả khi invokeMethod trả về true).QMetaObject :: invokeMethod trả về true, nhưng phương thức không bao giờ được gọi là

Đây là những gì tôi đang sử dụng:

QMetaObject::invokeMethod(this, "draw_widgets", Qt::QueuedConnection) 

tôi không nhận được bất kỳ thông báo lỗi hoặc bất cứ điều gì ... Nếu tôi sử dụng Qt :: AutoConnection hoặc Qt :: DirectConnection phương pháp này không được gọi , nhưng từ cùng một luồng của khóa học. Không phải từ thread GUI, đó là những gì tôi cần.

draw_widgets là một nơi công cộng loại void draw_widgets() và lớp của tôi kế thừa QObject và sử dụng macro Q_OBJECT.

Tôi sẽ đánh giá cao bất kỳ trợ giúp nào về vấn đề này hoặc cách kiểm tra lý do tại sao phương thức này không được gọi.

Cảm ơn.

+0

Tôi có một tình huống tương tự : Tôi có một lớp kế thừa từ QObject và sử dụng 'Q_OBJECT'. Ví dụ của lớp này được tạo ra trong vòng lặp chính. Sau đó, trong khi thực hiện một phương thức của cùng một lớp trong vòng lặp chính, tôi gọi 'QMetaObject :: invokeMethod (this," hideListsSlot ", Qt :: QueuedConnection);', trong đó 'void hideListsSlot()' là một khe công cộng của lớp học. Các khe cắm không bao giờ được gọi. – Giorgio

Trả lời

10

"true" đang cho bạn biết thư được xếp thành công. Điều đó không có nghĩa là thư được xếp hàng đã từng được xử lý ...

Giả sử chương trình của bạn có 10 luồng (Thread1-Thread10). Bạn xếp hàng một tin nhắn từ Thread7. Chủ đề nào sẽ được xếp hàng đợi? Và khi nào các mục trên hàng đợi này sẽ được xử lý?

Câu trả lời là mỗi QObject có một cái gì đó gọi là Thread Affinity và đây là chuỗi nơi một hàng đợi sẽ được chạy. Mối quan hệ mặc định là chủ đề mà đối tượng đã được tạo (nhưng bạn có thể thay đổi nó bằng QObject::moveToThread().)

Nếu bạn muốn xếp hàng gì đó vào chủ đề GUI, thì đối tượng được chỉ định bởi con trỏ của giao diện GUI phải có chủ đề GUI ái lực. Bạn có thể kiểm tra điều này với phương pháp QObject::thread().

Nhưng trong mọi trường hợp, không có vấn đề gì bạn xếp hàng để ... bạn phải có một số loại máy bơm tin nhắn chạy trên chủ đề đó. Hãy xem ví dụ QThread::exec(). Nếu mối quan hệ luồng của bạn là GUI thì có lẽ đây là trường hợp vì bạn đang chạy exec của ứng dụng.

(Là một sidenote, gọi điện trực tiếp đến QMetaObject::invokeMethod thường không cần thiết. Bạn có thể tạo ra một tín hiệu và buộc nó vào một khe cắm, sau đó phát ra tín hiệu thay cho invoke.)

+0

Cảm ơn rất nhiều câu trả lời của bạn. Tôi không biết về Thread Affinity. Thay đổi ái lực của đối tượng thành luồng GUI đã giải quyết được vấn đề. –

+0

@HostileFork đối diện sidenote, nếu bạn có quá nhiều vị trí, nó sẽ được tạo ra tín hiệu giống như khe, vì vậy trong trường hợp này, nó đủ công bằng để sử dụng 'QMetaObject :: invokeMethod (this," slot 1 ... n ", Qt :: QueuedConnection) '. –

+0

@HostileFork đối diện sidenote tiếp tục, cuộc gọi 'invokeMethod' shoud được palced trong khe bên trong kiểm tra điều kiện' if (QThread :: currentThread()! = Thread()) '. bằng cách này, khách hàng có thể gọi các khe cắm direclty. –

Các vấn đề liên quan