2013-02-24 38 views
29

Tôi gặp sự cố với tín hiệu Qt.Tín hiệu Qt (QueuedConnection và DirectConnection)

Tôi không hiểu cách hoạt động của DirectConnectionQueuedConnection?

Tôi rất biết ơn nếu ai đó sẽ giải thích khi nào nên sử dụng cái nào trong số này (mã mẫu sẽ được đánh giá cao).

+1

Xem http://stackoverflow.com/questions/11230080/qobject-based-class-has-a-queued-connection-to-itself và http://qt-project.org/doc/qt-4.8/ threads-qobject.html – user1929959

+2

Cụ thể bạn không hiểu gì về những điều này? Câu hỏi của bạn sẽ hướng đến "các tín hiệu và vị trí hoạt động như thế nào" mà không có điều đó, một chút rộng và được bao phủ bởi các tài liệu. – Mat

+0

Hmm .. theo như tôi hiểu, QueuedConnection nên được sử dụng khi người gửi và người nhận nằm trong các chủ đề khác nhau. Ví dụ, tôi có GUI Chủ đề (Chủ đề chính) và chuỗi mới (pThread) có tín hiệu ví dụ void doSomething(); và bộ thu là luồng GUI chính. Vì vậy, tôi phải sử dụng QueuedConnection không bao giờ nhớ nơi tôi sẽ gọi nó? (trong chủ đề GUI hoặc chuỗi mới, lệnh kết nối) Cảm ơn bạn .. – Nika

Trả lời

61

Bạn sẽ không thấy nhiều sự khác biệt trừ khi bạn đang làm việc với các đối tượng có mối quan hệ luồng khác nhau. Giả sử bạn có QObjects AB và cả hai đều được đính kèm với các chuỗi khác nhau. A có tín hiệu được gọi là somethingChanged()B có một khe gọi là handleChange().

Nếu bạn sử dụng một kết nối trực tiếp

connect(A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection); 

phương pháp handleChange() thực sự sẽ chạy trong thread 's A. Về cơ bản, nó như thể phát tín hiệu gọi phương thức khe "trực tiếp". Nếu B::handleChange() không an toàn cho chủ đề, điều này có thể gây ra một số lỗi (khó xác định). Ít nhất, bạn đang bỏ lỡ những lợi ích của chuỗi phụ.

Nếu bạn thay đổi phương thức kết nối thành Qt::QueuedConnection (hoặc trong trường hợp này, hãy để Qt quyết định nên sử dụng phương pháp nào), mọi thứ trở nên thú vị hơn. Giả sử thread của B đang chạy một vòng lặp sự kiện, phát ra tín hiệu sẽ gửi một sự kiện tới vòng lặp sự kiện của B. Event loop xếp hàng sự kiện và cuối cùng gọi phương thức slot bất cứ khi nào điều khiển trả về nó (nó là vòng lặp sự kiện). Điều này làm cho nó khá dễ dàng để đối phó với thông tin liên lạc giữa/trong số các chủ đề trong Qt (một lần nữa, giả sử chủ đề của bạn đang chạy vòng sự kiện địa phương của riêng mình). Bạn không phải lo lắng về khóa, vv vì vòng lặp sự kiện tuần tự hóa các yêu cầu vị trí.

Lưu ý: Nếu bạn không biết cách thay đổi mối quan hệ luồng của QObject, hãy xem QObject::moveToThread. Điều đó sẽ giúp bạn bắt đầu.

Sửa

Tôi nên làm rõ câu mở đầu của tôi. Nó tạo sự khác biệt nếu bạn chỉ định kết nối được xếp hàng đợi - ngay cả đối với hai đối tượng trên cùng một chuỗi. Sự kiện vẫn được đăng lên vòng lặp sự kiện của chuỗi. Vì vậy, các cuộc gọi phương pháp vẫn không đồng bộ, có nghĩa là nó có thể bị trì hoãn trong những cách không thể đoán trước (tùy thuộc vào bất kỳ sự kiện khác vòng lặp có thể cần phải xử lý). Tuy nhiên, nếu bạn không chỉ định một phương thức kết nối, phương thức trực tiếp sẽ tự động được sử dụng cho các kết nối giữa các đối tượng trên cùng một luồng (ít nhất nó nằm trong Qt 4.8).

+0

@ Jacob như vậy là nó không tốt hơn để trực tiếp gọi handleChange() như một chức năng bình thường thay vì đi vào sự nhầm lẫn SLOT SIGNAL cho trường hợp kết nối trực tiếp? –

+3

Cool_Coder: Lợi thế để gọi phương thức thông qua kết nối sig/slot là bạn không phải xây dựng kiến ​​thức về đối tượng 'B' vào' A' - bạn có thể cho phép người dùng của hai lớp xác định điều gì sẽ xảy ra khi 'somethingChanged 'được phát ra từ' A'. Điều đó có ý nghĩa? –

16

ngoài Jacob Robbins câu trả lời:

tuyên bố "Bạn sẽ không thấy nhiều sự khác biệt, trừ khi bạn đang làm việc với các đối tượng có mối quan hệ thân thread khác nhau" là sai;

phát tín hiệu cho kết nối trực tiếp trong cùng một chuỗi sẽ thực thi vị trí ngay lập tức, giống như cuộc gọi chức năng đơn giản.

phát tín hiệu cho kết nối được xếp hàng đợi trong cùng một chuỗi sẽ đẩy cuộc gọi vào vòng lặp sự kiện chủ đề, do đó việc thực thi sẽ luôn xảy ra xảy ra trễ.

QObject based class has a queued connection to itself

+0

Tôi hoàn toàn hiểu các tín hiệu và khe cắm ngay bây giờ, cảm ơn đã đề cập đến nó. – Nika

+0

Điểm tốt. Tôi luôn để Qt chọn phương thức kết nối trừ khi tôi có lý do chính đáng để chọn cái này hay cái kia ... vì vậy tôi có được một conn trực tiếp. khi các đối tượng trên cùng một luồng (sử dụng 4.8). Nó chắc chắn tạo ra sự khác biệt nếu bạn buộc một kết nối xếp hàng đợi. Tôi đã chỉnh sửa câu trả lời của mình để làm rõ. –

0

câu trả lời của Jacob là tuyệt vời. Tôi chỉ muốn thêm một ví dụ so sánh với Lập trình được nhúng.

Xuất phát từ nền RTOS/ISR được nhúng, thật hữu ích khi thấy các điểm tương đồng trong DirectConnection của Qt với hành vi Ưu tiên của ISR và QueuedConnection của Qt đối với các thư được xếp hàng trong RTOS giữa các tác vụ.

Lưu ý phụ: Đến từ nền được nhúng, rất khó để tôi không xác định được hành vi trong chương trình. Tôi không bao giờ rời bỏ lập luận như Auto, nhưng đó chỉ là ý kiến ​​cá nhân. Tôi thích tất cả mọi thứ được viết rõ ràng, và có đôi lúc khó khăn!