إعادة توجيه بيانات MFC إلى الخيط الرئيسي عبر postmessage

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

سؤال

لدي تطبيق C ++/MFC أحتاج إلى إعادة الهيكلة. التطبيق المستخدم لمعالجة معظم البيانات الموجودة على مؤشر الترابط الرئيسي ، وبالتالي حظر الإدخال ، والآن أريد تغييره ، بحيث يتم إجراء جميع تحديثات واجهة المستخدم الرسومية من خلال postmessage.

لسوء الحظ ، لا يمكنني العثور على مصدر جيد حول كيفية تحقيق هذا الهدف.

في الوقت الحالي ، أفكر في إنشاء قائمة انتظار ذات أولوية ، محمية بالقسم الحرج ، وخيط عامل (بينما (حقيقي)) يعالج قائمة الانتظار هذه ، وآلية ما بعد الحدود التي ترسل مؤشرات إلى البيانات إلى مؤشر الترابط الرئيسي.

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

المشكلة الثانية هي أن تطبيق آخر يمكن أن يرسل رسالة مخصصة إلى طلبي ، وقد يحاول طلبي أن يضعف WPARAM أو LPARAM كمؤشر وبالتالي تسبب AV.

هل يعرف أحد ما هي أفضل الممارسات لمثل هذه المهام؟

يمكن أن تكون البيانات محتوى HTML للتحكم في الويب ، أو غيرها من المحتوى لمربع القائمة ، أو القائمة المنسدلة ، إلخ.

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

المحلول

ستصل رسائلك إلى هناك. لست متأكدًا من سبب اعتقادك أن PostMessage ليس مضمونًا للعمل - إنه كذلك. (تحرير: افتراض postmessage () إرجاع صحيح! تحقق من رموز الإرجاع الخاصة بك!)

تريد تجنب استخدام قائمة انتظار لتوصيل البيانات بين مؤشرات الترابط. يجب حماية أي قائمة انتظار يمكن الوصول إليها من قبل كلا الموضوعين. إن إضافة الأقفال الصلبة على كلا الجانبين سيؤدي إلى تسلسل التطبيق الخاص بك.

بدلاً من ذلك ، قم بإنشاء بنية بيانات على الكومة باستخدام new يحتوي على بياناتك ، ثم أخبر الخيط الآخر "لقد حصلت على بيانات لك ، وهنا." ثم يأخذ موضوع الاسترداد ملكية مؤشر البيانات هذا ، وهو مسؤول عن deleteجي. القيام بذلك بهذه الطريقة ، لا توجد أقفال صلبة.

والآن ، فإن الحيلة الوحيدة هي اكتشاف جزء "أخبر الخيط الآخر" ، لكن هذا سهل أيضًا.

إذا كنت ترسل بيانات من مؤشر ترابط العامل إلى الموضوع الرئيسي ، فما عليك سوى استخدام PostMessage():

worker_thread_proc()
{
// ..

  // Create the data object you're going to pass to the MT
  MyData* data = new MyData;
  data->some_value_ = "foo";

  // Pass it:
  PostMessage(main_wnd, WM_YOU_HAVE_DATA, reinterpret_cast<WPARAM>(data), 0);
}

... يقوم الخيط الرئيسي بمعالجة هذا ، ثم يحذف البيانات:

MainWnd::OnYouHaveData(WPARAM wp, LPARAM)
{
  std::auto_ptr<MyData> data(reinterpret_cast<MyData*>(wp));
  my_widget->set_text(data->some_value_); // you get the idea
}

إذا كنت قلقًا بشأن الرسائل المخصصة للتطبيقات الخارجية التي تصطدم بك registerWindowsMessage () - التحدي الوحيد الخاص بك هنا هو اختيار الاسم الصحيح لرسالتك.

إذا كانت بيانات إرسالك من مؤشر الترابط الرئيسي إلى مؤشر ترابط العامل ، فيمكنك فعل الشيء نفسه أعلاه ، باستثناء بدلاً من استخدام PostMessage() لإرسال البيانات عبر الحائط ، يمكنك استخدام أيضًا QueueUserAPC () (التأكد من أن العامل الخاص بك في حالة انتظار قابلة للتنبيه - اقرأ الملاحظات في المستند postThreadMessage ().

تعديل:

بناءً على تعليقاتك في البروتوكول الاختياري ، أفهم الآن سبب قلقك بشأن عدم عمل ما بعد الولادة ().

نعم ، هناك حد صعب لحجم قائمة انتظار رسالة Windows. بشكل افتراضي ، يمكن أن يكون هناك 4000 رسالة فقط في قائمة الانتظار. (يمكن أن تعدل إعدادات التسجيل هذا إلى ما يصل إلى 10،000 كحد أقصى).

إذا كانت قائمة الانتظار ممتلئة ، فأي مكالمةPostMessage() سوف تفشل مع رمز الخطأ. عندما تقوم بالتحقق من getLasterror () (لا أتذكر رمز الخطأ الذي يتم إرجاعه الآن) ، سيكون من الواضح أن قائمة انتظار الرسائل ممتلئة.

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

نصائح أخرى

استخدم طابورتين ، أحدهما لطلبات العمل الذهاب إلى موضوع العمال وواحد للنتائج التي تعود إلى الخيط الرئيسي. يمكنك استخدام PostMessage لإيقاظ الموضوع الرئيسي وإخباره للتحقق من قائمة الانتظار ، لكنك لن تحتاج إلى أي معلمات في الرسالة.

لقد حلت مشكلة مماثلة منذ بعض الوقت. لقد صنعت قائمة انتظار مفردة للاحتفاظ بالبيانات (أو الإجراءات) التي تحتاج إلى التدفق من مؤشرات الترابط الخلفية إلى مؤشر ترابط واجهة المستخدم (الرئيسية). قائمة الانتظار محمية بواسطة قسم حرج. سيضع مؤشر ترابط الخلفية بياناته في قائمة الانتظار ونشر رسالة. لا تحتوي الرسالة على أي بيانات ، فهي بمثابة مكالمة إيقاظ بسيطة "مهلا ، موضوع رئيسي ، انظر إلى قائمة الانتظار ، هناك عمل من أجلك".

بهذه الطريقة ، لا تخاطر بتسريب أي ذاكرة أو موارد أخرى ؛ يمكن تدمير قائمة الانتظار بأمان مع جميع البيانات التي تحتوي عليها.

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