أريد ذاكرتي مرة أخرى! كيف يمكنني التخلص من السيطرة حقا؟

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

سؤال

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

void loadALoadOfStuff()
{
    while(tabControlToClear.Controls.Count > 0)
        tabControlToClear.Controls[0].Dispose();
    //I even put in:
    GC.Collect();
    GC.WaitForPendingFinalizers();
    foreach(String pagename in globalList)
        tabControlToClear.Controls.Add(MakeATab(pagename));
}

TabPage MakeATab(string tabText)
{
    TabPage newT = new MakeATab();
    newT.Text = tabText;
    //Fill page with controls with methods like this
    return newT;
}

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

تحديث: لقد كنت أشاهد إنشاء كائنات المستخدم وتدمير (TaskManager) ولاحظت أن أقوم بإنشاء صفحة علامات التبويب، وأضف معالج نقرة، وإضافة لوحة، وأضف لوحة، وأضف أزرارا، وضيف 2 أزرار معالجات النقر و Tooltips و Backimages (أعتقد أن هذا هو المكان المشكلة هي). يقول التطبيق إنه يخلق 8 عناصر جديدة، ولكن عندما أركض من خلال تخلصي، أزيل 4 فقط من الذاكرة. لقد كنت أحاول إزالة معالجات الأحداث، لكن يبدو أنه لا يحدث فرقا.

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

1: إذا كان لديك نصيحة أداة، تأكد من الوصول إليها! لا تفعل ما فعلت! على سبيل المثال:

هذا خطأ!

TabPage MakeATab(string tabText)
{
    TabPage newT = new MakeATab();
    ToolTip myTip = new ToolTip();
    newT.Text = tabText;
    //Fill page with controls with methods like this
    myTip.SetToolTip(newT, "Something to say");
    return newT;
}

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

2: قبل أي شيء، استدعاء tooltip.removeall (). هذا يزيل كل علاقات الضوابط. ملاحظة، إذا كنت تستخدم هذه النصيحة لعناصر تحكم أخرى، فقد فقدوا لتوه نصيحة الأداة.

3: قم بإزالة أي عناصر تحكم داخلية من Control.ControlCollection (إذا كانوا يستخدمون الذاكرة غير المدارة، أعتقد. أنا أفعل ذلك لأن ذلك يجعل تطبيقي يعمل حتى ...)

4: إزالة أي معالجات الأحداث المخصصة.

5: أخيرا، قم بالتخلص من الكائن. أنا جعلت وظيفة مررية سريعة التي تفعل ذلك جيدا.

    private void RecursiveDispose(Control toDispose)
    {
        while (toDispose.Controls.Count > 0)
            RecursiveDispose(toDispose.Controls[0]);

        if (toDispose.BackgroundImage != null)
            BackgroundImage = null;

        if (toDispose.GetType() == typeof(Button))
            toDispose.Click -= [Your Event];
        else if (toDispose.GetType() == typeof(TabPage))
            toDispose.DoubleClick -= [Your Event];
        else if (toDispose.GetType() == typeof(Label))
            toDispose.MouseMove -= [Your Event];

        toDispose.Dispose();
    }

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

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

المحلول

تحتاج إلى مسح أيضا المرجع.

while(tabControlToClear.Controls.Count > 0)
{ 
    var tabPage = tabControlToClear.Controls[0];
    tabControlToClear.Controls.RemoveAt(0);
    tabPage.Dispose(); 

    // Clear out events.

    foreach (EventHandler subscriber in tabPage.Click.GetInvocationList())
    {
        tabPage.Click -= subscriber;
    }
}

نصائح أخرى

في كتلة الرمز هذه، يمكنك الاتصال بالتخلص ولكن لا تقوم بإزالة المرجع:

while(tabControlToClear.Controls.Count > 0)
    tabControlToClear.Controls[0].Dispose();

تحتاج إلى إزالة جميع المراجع إلى عنصر التحكم (في مجموعة أدوات التحكم بالإضافة إلى أي معالجات حدث مسجل بالإضافة إلى أي مراجع أخرى قد تكون لديك) للتحكم في أن يكون مؤهلا للحصول على مجموعة القمامة.

void loadALoadOfStuff()
{
    while(tabControlToClear.Controls.Count > 0)
        tabControlToClear.Controls[0].Dispose();
    //I even put in:
    GC.Collect();
    GC.WaitForPendingFinalizers();
    foreach(String pagename in globalList)
        tabControlToClear.Controls.Add(MakeATab(pagename));
}

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

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

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

هذا هو أحد الأسباب التي يستخدمها نمط الحدث الضعيف، ولكن هذا سيكون سؤال جديد كامل.

(عمر كائنات UI عندما تقوم بمعدل ديناميكيا وهو UI هو حقل ألغام، تم القيام به بشكل جيد ل TaskManager للتحقق من أن الكود الخاص بك يعمل كما هو متوقع)

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