كيفية دمج حلقة Boost.Asio الرئيسية في إطار عمل واجهة المستخدم الرسومية مثل Qt4 أو GTK

StackOverflow https://stackoverflow.com/questions/1001032

سؤال

هل هناك أي طريقة لدمج Boost.Asio مع Qt4 (المفضل) أو حلقة GTK الرئيسية؟توفر GTK استطلاعًا (2) مثل واجهة برمجة التطبيقات (API)، لذلك يجب أن يكون ذلك ممكنًا من الناحية الفنية.توفر Qt طبقة شبكية خاصة بها، لكنني أفضل استخدام التعليمات البرمجية الموجودة المكتوبة لـ Boost.Asio.أريد دمجهم بدون باستخدام موضوع إضافي.

هل هناك أي مرجع لكيفية القيام بذلك لـ Qt4 (المفضل) أو GTKmm؟

شكرًا.

يحرر

أريد توضيح عدة أمور لتسهيل الإجابة.يوفر كل من QT و GTKMM وظيفة "Select Like":

لذا ، فإن السؤال هو ، كيفية دمج "المحددات/الملوقين" الحالية كمفاعل لتعزيز. io_service.اليوم، يمكن لـ Boost.Asio استخدام Select وkqueue وepoll و/dev/poll وiocp كخدمة مفاعل/proactor.أريد دمجها في الحلقة الرئيسية لإطار عمل واجهة المستخدم الرسومية.

أي اقتراحات وحلول (أفضل) هي موضع ترحيب.

هل كانت مفيدة؟

المحلول

إنه سؤال قديم إلى حد ما ولكن بالنسبة لأولئك الذين يقرؤونه الآن أود مشاركته رمز بلدي وهو تطبيق QAbstractEventDispatcher لتعزيز :: asio.

كل ما تحتاجه هو إضافة السطر التالي قبل إنشاء QApplication (عادة ما يكون في main()).

QApplication::setEventDispatcher(new QAsioEventDispatcher(my_io_service));

سيؤدي ذلك إلى تشغيل io_service مع تطبيق qt في مؤشر ترابط واحد دون زمن انتقال إضافي وانخفاض الأداء (كما هو الحال في الحل مع استدعاء io_service::poll() "من وقت لآخر").

لسوء الحظ، الحل الخاص بي مخصص لأنظمة posix فقط، لأنه يستخدم asio::posix::stream_descriptor .قد يحتاج دعم Windows إلى نهج مختلف تمامًا أو مشابه تمامًا - لا أعرف حقًا.

نصائح أخرى

بسيط:قم ببناء فتحة QT التي تستدعي io_service::poll_one() تنتمي إلى واجهة المستخدم الرسومية.قم بتوصيل تلك الفتحة بـ QT tick الإشارة.

في الصميم:لحسن الحظ بالنسبة لك، تم تصميم Boost.Asio بشكل جيد للغاية.هناك العديد من الخيارات حول كيفية توفير سلسلة تنفيذ للأجزاء الداخلية غير المتزامنة الأساسية.لقد ذكر الناس بالفعل استخدام io_service::run(), ، حظر المكالمة مع العديد من العيوب.

يُسمح لك فقط بالوصول إلى أدوات واجهة المستخدم الرسومية من سلسلة رسائل واحدة.تحتاج المواضيع الخارجية عمومًا إلى نشر الأحداث على واجهة المستخدم الرسومية إذا أرادت إجراء تغيير في أي عنصر واجهة مستخدم.هذا مشابه جدًا لكيفية عمل Asio.

النهج الساذج هو تخصيص مؤشر ترابط واحد (أو مؤقت) للتشغيل io_service::run() واطلب من معالج إكمال Asio أن ينشر إشارة واجهة المستخدم الرسومية.هذا سوف عمل.

بدلاً من ذلك، يمكنك استخدام ضمان أنه سيتم استدعاء معالجات الإكمال فقط في سلسلة تنفيذ الملف io_service المتصل.لم يكن لديك استدعاء مؤشر ترابط واجهة المستخدم الرسومية io_service::run() لأنه يحجب ويمكن أن يتعطل واجهة المستخدم الرسومية.بدلا من ذلك استخدم io_service::poll() أو io_service::poll_one().سيؤدي هذا إلى استدعاء أي معالجات إكمال Asio معلقة من سلسلة واجهة المستخدم الرسومية.نظرًا لأن المعالجات تعمل في سلسلة واجهة المستخدم الرسومية، فهي حرة في تعديل عناصر واجهة المستخدم.

الآن أنت بحاجة للتأكد من io_service يحصل على فرصة للجري بانتظام.أوصي بإجراء مكالمة إشارة واجهة المستخدم الرسومية المتكررة poll_one() بعض الاوقات.أعتقد أن QT لديها إشارة التجزئة التي من شأنها أن تفي بالغرض.يمكنك بالطبع تشغيل إشارة QT الخاصة بك لمزيد من التحكم.

إذا فهمت سؤالك بشكل صحيح، فلديك رمز مكتوب لـ Boost.Asio.ترغب في استخدام هذا الرمز داخل تطبيق واجهة المستخدم الرسومية.

ما هو غير واضح في سؤالك هو ما إذا كنت تريد التفاف طبقات شبكة Qt/Gtk من خلال asynio حتى تعمل التعليمات البرمجية الخاصة بك، إذا كنت تبحث فقط عن حل للحصول على كل من حلقة حدث واجهة المستخدم الرسومية وasynio معًا.

سأفترض الحالة الثانية.

يمتلك كل من Qt وGtk طرقًا لدمج الأحداث الخارجية في حلقة الأحداث الخاصة بهما.انظر على سبيل المثال qtgtk حيث يتم توصيل حلقة حدث Qt بـ Gtk.

في حالة Qt المحددة، إذا كنت تريد إنشاء أحداث لـ Qt، فيمكنك استخدام الفئة التالية: QAbstractEventDispatcher.

بعد إلقاء نظرة سريعة على Boost asio، أعتقد أنك بحاجة إلى القيام بما يلي:

  • لديك QTimer متكرر بمدة صفرية تستدعي io_service::run() طوال الوقت.بهذه الطريقة، سوف يقوم Boost::asio باستدعاء معالج الإكمال الخاص بك بمجرد اكتمال العملية غير المتزامنة.
  • في معالج الإكمال لديك، هناك خياران:
    • إذا كانت عملية الإكمال طويلة، ومنفصلة عن واجهة المستخدم الرسومية، فقم بعملك وتأكد من الاتصال بـ qApp.processEvents() بانتظام للحفاظ على استجابة واجهة المستخدم الرسومية
    • إذا كنت تريد فقط التواصل مرة أخرى مع واجهة المستخدم الرسومية:
      1. تحديد العرف QEvent يكتب
      2. اشترك في هذا الحدث
      3. انشر الحدث الخاص بك إلى حلقة حدث Qt باستخدام QCoreApplication::postEvent().

دمج حقيقي للحلقات الرئيسية يكون ممكن.إنه مجرد ألم كبير (ولم أجربه فعليًا بعد).

من المحتمل أن يكون تشغيل io_service::run() على موضوع منفصل هو الحل الأمثل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top