سؤال

أنا أعمل على مشروع واسع النطاق حيث تم توفير إطار عمل مخصص (جيد وقوي) وعلينا أن نستخدم ذلك لإظهار النماذج ووجهات النظر.


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

StrategyForm (إطار نافذة مخصص) يحتوي على StrategyEditor.
StrategyEditor يحتوي على StrategyTab.
StrategyTab يحتوي على StrategyCanvas.

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


الآن ، في وقت التشغيل ، يفتح المستخدم العديد من كائنات الإستراتيجية (التي تؤدي إلى إنشاء كائن استراتيجي جديد.) بعد إنشاء تقريبًا. 44 كائنات الإستراتيجية ، نرى أن كائن المستخدم يعامل (سأستخدم uoh من هنا فصاعدًا) الذي تم إنشاؤه بواسطة التطبيق يصل إلى حوالي 20 ألف+، بينما في التسجيل هو المبلغ الافتراضي للمقابض هو 10K. اقرأ المزيد عن كائنات المستخدم هنا. أوضح الاختبار على الأجهزة المختلفة أن عدد كائنات الإستراتيجية التي تم فتحها يختلف عن الرسالة المنبثقة - على M/C إذا كان 44 ، يمكن أن يكون 40 على آخر.

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

لقد اعتقدنا أولاً أنه لم يكن قضية غير ذاكرة. ولكن بعد ذلك قراءة المزيد عن new في C# ساعد في فهم أنه سيتم طرح استثناء إذا نفد التطبيق من الذاكرة. هذه ليست مشكلة في الذاكرة ، أشعر (أظهر مدير المهام أيضًا ذاكرة 1.5 جيجابايت+ المتاحة.)


مواصفات M/C
CORE 2 DUO 2GHZ+
4 جيجابايت ذاكرة الوصول العشوائي
80 جيجابايت+ مساحة قرص مجانية لملف الصفحة
مجموعة الذاكرة الافتراضية: 4000 - 6000


أسئلتي


س 1. هل هذا يبدو وكأنه مشكلة في الذاكرة وأنا مخطئ لأنها ليست كذلك؟
س 2. هل هذه النقطة إلى استنفاد UOHs الحرة (كما أفكر) والتي تؤدي إلى فشل إنشاء مقابض النوافذ؟
س 3. كيف يمكننا تجنب تحميل StrategyEditor كائن (ما وراء العتبة ، مراقبة الاستخدام الحالي لأوه)؟ (نحن نعرف بالفعل كيفية جلب عدد uOHs المستخدمة ، لذلك لا تذهب إلى هناك.) ضع في اعتبارك أن الدعوة إلى new StrategyForm() خارج عن سيطرة المكون الخاص بي.
س 4. أنا مرتبك بعض الشيء - ماذا يتعامل مع كائنات المستخدم بالضبط؟ هل يتحدث MSDN عن أي كائن نقوم بإنشائه أو فقط بعض الكائنات المحددة مثل مقابض النوافذ ، ومقابض المؤشر ، ومقابض أيقونة؟
س 5. ما هي الأسباب بالضبط لاستخدام UOH؟ (تقريبا مثل Q4)

سأكون ممتنًا حقًا لأي شخص يمكنه أن يعطيني بعض الإجابات المطلع. شكرا جزيلا! قون

تحديث
استنادًا إلى إجابة Stakx ، يرجى ملاحظة أن Windows التي يتم فتحها ، سيتم إغلاقها بواسطة المستخدم فقط. هذا نوع من وضع تطبيق MDI حيث يتم فتح الكثير من Windows Windows. لذا، Dispose لا يمكن استدعاؤها وقتما نريد.

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

المحلول

س 1

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

س 4

أنا أفهم كائن المستخدم أن تكون أي كائن جزء من واجهة المستخدم الرسومية. على الأقل حتى Windows XP ، أقامت Windows UI API USER.DLL (واحدة من DLLs الأساسية التي تشكل Windows). في الأساس ، يتكون واجهة المستخدم من "النوافذ". جميع عناصر التحكم ، مثل الأزرار ومربعات النص ومربعات الاختيار ، هي نفس الشيء داخليًا ، وهي "Windows". لإنشاءها ، يمكنك الاتصال بوظيفة WIN32 API CreateWindow. ستؤدي هذه الوظيفة بعد ذلك إلى إرجاع مقبض إلى "النافذة" التي تم إنشاؤها (عنصر واجهة المستخدم ، أو "كائن المستخدم").

لذلك أفترض أن أ معالجة كائن المستخدم هو مقبض كما أعيدها هذه الوظيفة. (يعتمد WinForms على API Old Win32 وبالتالي سيستخدم CreateWindow وظيفة.)

س 2

في الواقع ، لا يمكنك إنشاء أكبر عدد ممكن من عناصر التحكم في واجهة المستخدم كما تريد. كل تلك المقابض تم استرجاعها من خلال CreateWindow يجب تحريرها في مرحلة ما. في Winforms ، أسهل وأكثر طريقة أمان للقيام بذلك هي من خلال استخدام using حظر أو عن طريق الاتصال Dispose:

using (MyForm form = new MyForm())
{
    if (form.ShowDialog() == DialogResult.OK) ...
}    

أساسا ، كل شيء System.Windows.Forms.Control يمكن ان يكون Disposeد ، ويجب التخلص منها. في بعض الأحيان ، يتم ذلك من أجلك تلقائيًا ، لكن يجب ألا تعتمد عليه. دائماً Dispose تحكم واجهة المستخدم عندما لم تعد بحاجة إليها.

ملاحظة على Dispose للأشكال المشروطة والوحشية:

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

س 5

في كل مرة تقوم فيها بإنشاء كائن واجهة المستخدم ، يقوم WinForms داخليًا بإجراء المكالمات CreateWindow. هذه هي الطريقة التي يتم بها تخصيص المقابض. ولم يتم تحريرهم حتى يتم الاتصال المقابل بـ DestroyWindow مصنوع. في Winforms ، يتم تشغيل هذه المكالمة من خلال Dispose طريقة أي System.Windows.Forms.Control. (ملاحظة: على الرغم من أنني متأكد من هذا الأمر ، إلا أنني أخمن قليلاً. قد لا أكون صحيحًا بنسبة 100 ٪. إن إلقاء نظرة على Winforms Internals باستخدام Reflector سيكشف عن الحقيقة.)

س 3

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

ومع ذلك ، يمكنك تتبع عدد العدد StrategyEditorيتم فتح s في أي وقت (زيادة عداد كلما تم إنشاء مثيل له ، وتقليله كلما تم إغلاق واحد - يمكنك تتبع الأخير باستخدام FormClosing/FormClosed حدث من النموذج ، أو في Dispose طريقة التحكم). ثم يمكنك الحد من عدد فتح في وقت واحد StrategyEditorS إلى رقم ثابت ، قل 5. إذا تم تجاوز الحد ، فيمكنك رمي استثناء في المُنشئ ، بحيث لا يتم إنشاء مثيلات أخرى. بالطبع لا أستطيع أن أقول ما إذا كان StrategyForm سوف يتعامل مع استثناء من StrategyEditor مُنشئ جيد ...

public class StrategyEditor : ...
{
    public StrategyEditor()
    {
        InitializeComponent();

        if (numberOfLiveInstances >= maximumAllowedLiveInstances)
            throw ...;
        // not a nice solution IMHO, but if you've no other choice...
    }
}

في كلتا الحالتين ، يحد من عدد مثيله StrategyEditorيبدو S وكأنه حل مؤقت لي ولن يحل المشكلة الحقيقية.

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