هل من الممكن "فصل" العديد من سلاسل واجهة المستخدم الرسومية؟(عدم إيقاف النظام عند Application.Run)

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

  •  08-06-2019
  •  | 
  •  

سؤال

هدفي

أرغب في الحصول على سلسلة معالجة رئيسية (غير واجهة المستخدم الرسومية)، وأن أكون قادرًا على فصل واجهات المستخدم الرسومية في سلاسل العمليات الخلفية الخاصة بها حسب الحاجة، واستمرار عمل مؤشر الترابط الرئيسي غير واجهة المستخدم الرسومية.وبعبارة أخرى، أريد أن يكون مؤشر ترابط واجهة المستخدم الرسومية الرئيسي الخاص بي هو مالك مؤشر ترابط واجهة المستخدم الرسومية وليس العكس.لست متأكدًا من أن هذا ممكن حتى مع Windows Forms(؟)

خلفية

لدي نظام قائم على المكونات حيث تقوم وحدة التحكم بتحميل التجميعات بشكل ديناميكي وإنشاء مثيل لها وتشغيل الفئات التي تنفذ أمراً شائعاً IComponent واجهة مع طريقة واحدة DoStuff().

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

يبدو عمر النظام الكامل هكذا

  1. يبدأ التطبيق.
  2. تحقق من ملف التكوين لتحميل المكونات.تحميلها.
  3. لكل مكون، تشغيل DoStuff() لتهيئته وجعله يعيش حياته الخاصة في خيوطه الخاصة.
  4. استمر في القيام بملك العمل الرئيسي للتطبيق، إلى الأبد.

لم أتمكن بعد من تنفيذ النقطة 3 بنجاح إذا قام المكون بتشغيل واجهة المستخدم الرسومية DoStuff().إنه ببساطة يتوقف حتى يتم إغلاق واجهة المستخدم الرسومية.ولن يتقدم البرنامج إلى النقطة 4 إلا بعد إغلاق واجهة المستخدم الرسومية.

سيكون أمرًا رائعًا إذا تم السماح لهذه المكونات ببدء تشغيل واجهات المستخدم الرسومية لنماذج Windows الخاصة بها.

مشكلة

عندما يحاول أحد المكونات تشغيل واجهة المستخدم الرسومية (GUI). DoStuff() (السطر الدقيق من التعليمات البرمجية هو عند تشغيل المكون Application.Run(theForm))، المكون ومن ثم "يتوقف" نظامنا عند Application.Run() سطر حتى يتم إغلاق واجهة المستخدم الرسومية.حسنًا، تعمل واجهة المستخدم الرسومية التي تم تشغيلها للتو بشكل جيد، كما هو متوقع.

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

public class MyComponent1: IComponent
{
    public string DoStuff(...) { // write something to the database  }
}

public class MyComponent2: IComponent
{
    public void DoStuff()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form());

        // I want the thread to immediately return after the GUI 
        // is fired up, so that my main thread can continue to work.
    }
}

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

public void DoStuff()
{
    new Thread(ThreadedInitialize).Start()
}

private void ThreadedInitialize()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form());
}

هل من الممكن فصل واجهة المستخدم الرسومية والعودة بعد ذلك Application.Run()?

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

المحلول

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

ومع ذلك، يمكنك تمرير سياق التطبيق (بدلاً من نموذج () جديد) إلى طريقة Application.Run وApplicationContext يمكن استخدامهما لتشغيل عدة نماذج في وقت واحد.لن ينتهي طلبك إلا عندما يتم إغلاق كل هذه الطلبات.انظر هنا: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

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

نصائح أخرى

أنا متأكد من أن هذا ممكن إذا قمت باختراقه بقوة كافية، لكنني أقترح أنها ليست فكرة جيدة.

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

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

أفضل رهان لك هو القيام بذلك على النحو التالي:

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

لست متأكدًا مما إذا كان هذا صحيحًا، لكنني أتذكر تشغيل نماذج النوافذ من تطبيق وحدة التحكم بمجرد تحديث النموذج واستدعاء newForm.Show() عليه، إذا كانت مكوناتك تستخدم ذلك بدلاً من Application.Run() ثم الجديد لا ينبغي أن يمنع النموذج.

بالطبع سيكون المكون مسؤولاً عن الحفاظ على مرجع للنماذج التي يقوم بإنشائها

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