Archief - C# Winforms: error creating window handle

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Recipe4hate

Legacy Member
Hallo allemaal,

Ik ben op een vreemd, doch imo wel logisch probleem gestuit bij het bouwen van een grote Winforms app in C# (dotnet4.0).

Ik heb een Flowlayoutpanel dat verantwoordelijk is voor het tonen van een lijst van user controls.
De user control bestaat uit enkele panels, labels, 2 richtextboxes en een paar 16x16 afbeeldingen.

Wanneer er een paar van deze controls aan de flowlayoutpanel worden toegevoegd, gaat alles vlotjes.
Echter wanneer er meer (laat ons zeggen vanaf 100) controls moeten worden getoond, dan vertraagt alles visueel ineens sterk.
Bij momenten krijg ik ook de error 'Error creating window handle'.
Wanneer ik in Taskmanager ga kijken, merk ik dat op dat moment de USER Objects grens van 10000 is bereikt/wordt overschreden.

Volgens mij zijn er geen leaks, want wanneer ik de user controls van de panel haal (via code), daalt mijn USER Objects aantal terug naar een normaal resultaat (< 100).

Nu is mijn vraag niet hoe ik de grens kan overschrijden, want qua performance is dit niet haalbaar, maar hoe ik dit probleem kan omzeilen?
Ik heb ergens gelezen dat je eventueel user controls naar images kan omzetten en deze tonen tot je de control effectief nodig hebt. Jammer genoeg werkt dit niet direct met richtextboxes... en lijkt het hele proces me redelijk omslachtig? (prove me otherwise ;))

Zeker niet onbelangrijk: het is niet nodig om alle controls tegelijk te tonen.
Wel moet ik berekeningen kunnen maken met data uit alle controls (maar dit lijkt me wel mogelijk door een generic list van de user controls bij te houden en van hieruit data te extracten > gaat overigens wel zeer vlot -probleem ligt dus echt bij het visuele).
Ook moet de user snel over alle user controls kunnen scrollen om ze te evalueren.

Misschien moet ik een soort van paging/scrolling ipv de flowlayoutpanel-scrollbar implementeren? Zo hoeven niet alle user controls tegelijk aan de panel gekoppeld te zijn.
Heeft iemand hier tips/voorbeelden van?

Suggesties en opmerkingen zijn zeer welkom!

ultddave

Legacy Member
Dus als ik het goed begrijp wil je heel veel invoervelden met uitleg (labels) tonen waar de gebruiker data/parameters kan invullen?
Kunnen INI of config files hier niet bij helpen, in de vorm van (als voorbeeldje dan):
Code:
// GUI parameters
<key1>=<value1>
<key2>=<value2>
// AI parameters
<key3>=<value3>
<key4>=<value4>
Om die gegevens op te vragen?

Of is het eerder zoiets: bijvoorbeeld het register van windows visualiseren door labels + invoerveldjes (voor waarden te veranderen) in een desktop application?
Dan zou ik eerder kiezen voor panels met tabbladen; TabControl in C# als ik goed heb opgezocht ;).

In elke tab kunt ge dan zelfs nog een lijst/tabel plaatsen moest het niet op het scherm passen.

Widgets van een bepaalde tab kunt ge deleten als ge van tab verandert (aangezien het heel veel data blijkt te zijn).

Eventueel een soort simpel cachingalgoritme gebruiken zoals LRU-2 (Least Recently Used 2)? Waarbij je de onlangs gebruikt controls toch nog kan bijhouden in een cache.

Ben maar wat luidop aan het meedenken ^^.

Recipe4hate

Legacy Member
Het zijn eigenlijk berekeningen die moeten worden weergeven.
Het gaat over vrachten die bepaalde kosten met zich meedragen. De gebruiker kan in zo'n user control zien hoe een bepaalde 'charge' of 'rate' berekend wordt en op basis van welke selecties / consolidaties (sommige goederen worden samen berekend, andere niet, afhankelijk van zeer veel factoren).
Om de gebruiker door het bos de bomen nog te laten zien, moet dus heel veel detail weergegeven worden.

Er zijn dus geen invoervelden. De gegevens komen oorspronkelijk van een SQL databron en gaan er uiteindelijk ook terug heen, maar lopen momenteel door een heel veld van logic en rules en komen uiteindelijk op het punt waar de user ze moet controleren en goed-of afkeuren.

Tabbladen lijken me niet doenbaar, aangezien het effectief teveel data gaat zijn om nog gebruiksvriendelijk te zijn en te kunnen opsplitsen :).

Caching weet ik niet of nodig is. Ik heb al mijn user controls in een generic list in het geheugen (gaat zeer performant), dus ze zijn al soort van 'gecached'. Echter het toevoegen/verwijderen van teveel user controls aan mijn panel geeft problemen.
Visuele acties erna (zoals openklappen of sluiten van zo'n control -beetje te vergelijken met DIVS in html) gaan ook heel traag, logische acties (zoals bepaalde data uit iedere control halen) gaat tevens zeer snel.

Meedenken is zeker welkom. Kan ik alleen maar van leren!

Oorspronkelijk werd dit gedeelte weergegeven als 1 grote blok in-vorm-gegoten tekst. Dit bleek echter niet gebruiksvriendelijk genoeg, waardoor ik nu die blok tekst in stukken knip en in openklikbare controls plak.

Moto

Legacy Member
De user control bestaat uit enkele panels, labels, 2 richtextboxes en een paar 16x16 afbeeldingen.
Die images worden toch deftig gedisposed? anders kunnen die ook nogal snel window handles vreten

anyway
Ge kunt kijken als er niemand een virtual flowlayoutpanel gemaakt heeft naar het principe van een virtual grid waar ge dus enkel het zichtbare deel rendered.
Ge zou dat natuurlijk ook zelf kunnen gaan maken maar dat is dus wel veel gezeik omdat juist te krijgen, ge moet elke resize / scroll event deftig opvangen dat nog allemaal flicker vrij krijgen en dan ook natuurlijk zaken als tabs gebruiken, enz enz enz

Makkelijker is misschiens een grid zoeken die virtual rendering kan doen en waarvoor ge custom cell controls kunt maken

Effe gezocht blijkbaar heeft de standaard DataGridView een virtual mode en kan die ook custom controls aan
How to: Host Controls in Windows Forms DataGridView Cells

Weet wel niet als die goed is, ik gebruik op het werk syncfusion en dat is daarmee zijn zo'n dingen geen probleem maar is 3rd party + betalend

ultddave

Legacy Member
Ah bedankt voor de info ;).

Dus, als ge een stuk of 300 "user controls" (die elk nog die richtextboxen, panels, labels, ... bevatten) wilt tonen.
=> Dat is te groot in verticale richting.
Dus ge moet dan gaan scrollen
=> Constante repaint => traag.

Aangezien uw "user controls" redelijk strak gedefinieerd lijken te zijn (allemaal hetzelfde maar verschillende inhoud in de labels/textboxen etc), zullen die ook even groot zijn(?)

- Kunt ge dan niet via trial-and-error kijken hoeveel er op uw scherm passen. Bijvoorbeeld er passen er ongeveer 10 op uw scherm.

- Dus ge voegt elke keer 10 user controls toe aan uw panel (dat panel zou ge in principe ook al kunnen cachen, zodat ge elk panel ook bijhoudt) => voer een repaint uit.

- Gebruiker doet zijn werk.

En onderaan zet je een knop "next" en die doet => verwijder panel (en/of inhoud) en doe de volgende 10 in een dit (of nieuwe) panel.

In principe zou ge zelfs twee knoppen kunnen toevoegen "accept and continue" en "decline and continue" om dat "toelaten/weigeren" ook te integreren.

--

Of misschien ergens iets fixen met die invalidate en repaint functies te herimplementeren zodat die in bepaalde gevallen even niet zorgen voor een repaint.

Of optimaliseren met Double buffering; How to: Reduce Graphics Flicker with Double Buffering for Forms and Controls

Of dit gebruiken; winforms - C# Why use SuspendLayout()? - Stack Overflow

Basically it's if you want to adjust multiple layout-related properties - or add multiple children - but avoid the layout system repeatedly reacting to your changes. You want it to only perform the layout at the very end, when everything's "ready".

Recipe4hate

Legacy Member
Merci alletwee, zeer leerrijk :)

@ultddave: Het is niet zo zeer het double bufferen (scrollen van de panel) dat voor problemen zorgt. Immers: eenmaal de objecten op mijn panel staan, loopt het vlot.
Blijkbaar is het grootste probleem: het toevoegen en verwijderen van controls van de panel en het openen/sluiten van meerdere controls tegelijk (via een collapse all method), eenmaal ze op het panel staan.


Wel ga ik inderdaad waarschijnlijk proberen een tweede lijst bijhouden die enkel de "actieve" controls bevat en een soort pop-mechanisme bevat om objecten erin/eruit te halen.

@Moto: hmm, dat van de images is een goeie opmerking.
Standaard werk ik met static images die bij het constructen aan de control worden toegekend:

Code:
    public partial class CostLineReport : UserControl
    {
        #region CONSTANTS
        public static int pnlWidth = 870;
        public static int pnlHeightBase = 112;
        public static int pnlHeightExtended = 415;
        public static int pnlHeightCollapsed = 30;
        public static Color ColorNeutral = Color.FromArgb(176, 196, 222);
        public static Color ColorApprove = Color.FromArgb(173, 255, 47);
        public static Color ColorDisapprove = Color.FromArgb(255, 99, 71);
        public static Image ImageApprove = Image.FromFile(@"Images\tableAdd.png");
        public static Image ImageDisapprove = Image.FromFile(@"Images\tableDelete.png");
        public static Image ImageDetail = Image.FromFile(@"Images\tableDetail.png");
        public static Image ImageCollapse = Image.FromFile(@"Images\compile-warning.png");
        public static Image ImageViewRecords = Image.FromFile(@"Images\table.png");
        public static Image ImageCalculationInclude = Image.FromFile(@"Images\add.png");
        public static Image ImageCalculationExclude = Image.FromFile(@"Images\delete.png");
        #endregion
//etc...
Code:
#region CTORS
        public CostLineReport(string Title, string mainText, string detailText, ACostLine line, ApprovalState apst = ApprovalState.Neutral, ViewState vwst = ViewState.Base, DisplayState dpst = DisplayState.Full)
        {
            InitializeComponent();
            _IsCollapsed = false;
            this._ApprovalState = apst;
            this._ViewState = vwst;
            this._DisplayState = dpst;
            this._CalculationState = CalculationState.Excluded;
            this.picApprove.Click += new EventHandler(Approve);
            this.picDisapprove.Click += new EventHandler(Disapprove);
            this.picDetail.Click += new EventHandler(ResizeControl);
            this.picCollapse.Click += new EventHandler(CollapseControl);
            this.picViewRecords.Click += new EventHandler(ShowRecords);
            this.picCalculation.Click += new EventHandler(SwitchCalculateState);
            this.rtMainData.Text = mainText;
            this.rtDetail.Text = detailText;
            this.lblTitle.Text = Title;
            this._CurrentCostline = line;
            new ToolTip().SetToolTip(this.picApprove, "Approve this line");
            new ToolTip().SetToolTip(this.picDisapprove, "Disapprove this line");
            new ToolTip().SetToolTip(this.picCollapse, "Collapse this line");
            new ToolTip().SetToolTip(this.picDetail, "Show detail");
            new ToolTip().SetToolTip(this.picViewRecords, "View associated recordset");
            new ToolTip().SetToolTip(this.picCalculation, "Include/Exclude from calculation");
            this.picApprove.Image = CostLineReport.ImageApprove;
            this.picDisapprove.Image = CostLineReport.ImageDisapprove;
            this.picDetail.Image = CostLineReport.ImageDetail;
            this.picCollapse.Image = CostLineReport.ImageCollapse;
            this.picViewRecords.Image = CostLineReport.ImageViewRecords;
            this.picCalculation.Image = CostLineReport.ImageCalculationExclude;
            Recolor();
            DrawDisplayItems();
        }
        #endregion

Recipe4hate

Legacy Member
Goed, ik heb nu een PageList geschreven op basis van IEnumerable<T>. Deze houdt zowel al mijn data bij, als een 'page' die een bepaald aantal elementen bijhoudt en kan 'scrollen'.

Nu heb ik echter het volgende probleem:
Volgens mij blijven de usercontrols ergens in memory zitten op mijn panel.
Ik verwijder mijn controls van mijn panel via de panel.Controls.Clear() methode. Ik kan ze echter niet gaan disposen, want ik dan zou ik mijn PageList om zeep helpen?!

Zo merk ik dat dus mijn aantal User objects in Taskmanager stijgt bij het 'pagen' van mijn list en constant blijft bij het verwijderen van de controls op het panel. (dus wanneer ik mijn list opnieuw page met bestaande objects, verandert er niks aan het aantal User objects, wanneer ik nieuwe items page, stijgt het aantal...).

Daar ik bepaalde waardes bijhou op mijn control, kan ik dus niet zomaar alle controls op de panel gaan disposen.
Ik zou dus mijn controls uit het geheugen van mijn GUI willen halen maar niet uit mijn generic lists, zodat ze gemakkelijk hergebruikt kunnen worden.
-Bestaat er hiervoor een manier?
-Moet ik telkens nieuwe controls gaan aanmaken en oude verwijderen?
-Gaan mijn objecten die binnen de control zitten (maar ook aan andere objecten gekoppeld zijn) ook gedisposed worden?


Alvast hartelijk dank!

Recipe4hate

Legacy Member
Nog eens een update (dat begint hier bena een blog te worden ;) )

Ik heb ervoor gezorgd dat mijn control en zijn data gescheiden zijn, waardoor er nu nog maar 1 extern object in de control zit.
Dit extern object wordt uiteraard vaak aangeroepen, maar so be it :-)

Nu kan ik dus een dispose callen op mijn user control zonder de interne data om zeep te helpen. Ik zie dat het aantal USER objects enorm daalt na het disposen, wat wil zeggen dat het goed werkt...MAAR! niet alles wordt blijkbaar gecleared (nog steeds ergens memory leaks dus....)...

Zouden jullie mij kunnen zeggen wat er nog mogelijk in het geheugen blijft en wat ik eraan kan doen?
(ik verwacht iets als delegates (events), images, tooltips, ...?

Mijn user control:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Classes.CustomControls
{
    public partial class CostLineReport : UserControl, IDisposable
    {
        #region CONSTANTS
        public static int pnlWidth = 870;
        public static int pnlHeightBase = 112;
        public static int pnlHeightExtended = 415;
        public static int pnlHeightCollapsed = 30;
        public static Color ColorNeutral = Color.FromArgb(176, 196, 222);
        public static Color ColorApprove = Color.FromArgb(173, 255, 47);
        public static Color ColorDisapprove = Color.FromArgb(255, 99, 71);
        public static Image ImageApprove = Image.FromFile(@"Images\tableAdd.png");
        public static Image ImageDisapprove = Image.FromFile(@"Images\tableDelete.png");
        public static Image ImageDetail = Image.FromFile(@"Images\tableDetail.png");
        public static Image ImageCollapse = Image.FromFile(@"Images\compile-warning.png");
        public static Image ImageViewRecords = Image.FromFile(@"Images\table.png");
        public static Image ImageCalculationInclude = Image.FromFile(@"Images\add.png");
        public static Image ImageCalculationExclude = Image.FromFile(@"Images\delete.png");
        #endregion

        #region FIELDS
        private CostLineReportData _Costlinereportdata;
        private ToolTip ttpApprove;
        private ToolTip ttpDisapprove;
        private ToolTip ttpCollapse;
        private ToolTip ttpDetail;
        private ToolTip ttpViewRecords;
        private ToolTip ttpCalculation;
        #endregion

        #region CTORS
        public CostLineReport(CostLineReportData line)
        {
            InitializeComponent();
            //
            this._Costlinereportdata = line;
            //
            this.picApprove.Click += new EventHandler(Approve);
            this.picDisapprove.Click += new EventHandler(Disapprove);
            this.picDetail.Click += new EventHandler(ResizeControl);
            this.picCollapse.Click += new EventHandler(CollapseControl);
            this.picViewRecords.Click += new EventHandler(ShowRecords);
            this.picCalculation.Click += new EventHandler(SwitchCalculateState);
            //
            this.rtMainData.Text = _Costlinereportdata.Maintext;
            this.rtDetail.Text = _Costlinereportdata.Detailtext; ;
            this.lblTitle.Text = _Costlinereportdata.Title;
            //
            ttpApprove = new ToolTip();
            ttpDisapprove = new ToolTip();
            ttpCollapse = new ToolTip();
            ttpDetail = new ToolTip();
            ttpViewRecords = new ToolTip();
            ttpCalculation = new ToolTip();
            ttpApprove.SetToolTip(this.picApprove, "Approve this line");
            ttpDisapprove.SetToolTip(this.picDisapprove, "Disapprove this line");
            ttpCollapse.SetToolTip(this.picCollapse, "Collapse this line");
            ttpDetail.SetToolTip(this.picDetail, "Show detail");
            ttpViewRecords.SetToolTip(this.picViewRecords, "View associated recordset");
            ttpCalculation.SetToolTip(this.picCalculation, "Include/Exclude from calculation");
            //
            this.picApprove.Image = CostLineReport.ImageApprove;
            this.picDisapprove.Image = CostLineReport.ImageDisapprove;
            this.picDetail.Image = CostLineReport.ImageDetail;
            this.picCollapse.Image = CostLineReport.ImageCollapse;
            this.picViewRecords.Image = CostLineReport.ImageViewRecords;
            this.picCalculation.Image = CostLineReport.ImageCalculationExclude;
            //
            Recolor();
        }
        #endregion

        #region PROPERTIES
        public RichTextBox MainTextBox
        { get { return this.rtMainData; } }
        public RichTextBox DetailTextBox
        { get { return this.rtDetail; } }
        public Label TitleLabel
        { get { return this.lblTitle; } }
        public PictureBox CalculateControl
        { get { return this.picCalculation; } }
        #endregion

        #region METHODS
        private void Approve(object o, EventArgs e)
        {
            _Costlinereportdata.Approve();
            Recolor();
        }
        private void Disapprove(object o, EventArgs e)
        {
            _Costlinereportdata.Disapprove();
            Recolor();
        }
        private void ResizeControl(object o, EventArgs e)
        {
            _Costlinereportdata.SwitchSize();
            switch(_Costlinereportdata.Viewstate)
            {
                case ViewState.Base:
                    this.Height = CostLineReport.pnlHeightBase;
                    break;
                case ViewState.Extended:
                    this.Height = CostLineReport.pnlHeightExtended;
                    break;
            }
        }
        private void CollapseControl(object o, EventArgs e)
        {
            _Costlinereportdata.Collapse();
            if (_Costlinereportdata.Collapsed)
                this.Height = CostLineReport.pnlHeightCollapsed;
            else
                this.Height = CostLineReport.pnlHeightBase;
        }
        private void Recolor()
        {
            switch (_Costlinereportdata.Approvalstate)
            {
                case ApprovalState.Approved:
                    foreach (Control c in pnlColorIndicator.Controls)
                    {
                        if (c is PictureBox)
                            ((PictureBox)c).BackColor = CostLineReport.ColorApprove;
                    }
                    pnlColorIndicator.BackColor = CostLineReport.ColorApprove;
                    break;
                case ApprovalState.Disapproved:
                    foreach (Control c in pnlColorIndicator.Controls)
                    {
                        if (c is PictureBox)
                            ((PictureBox)c).BackColor = CostLineReport.ColorDisapprove;
                    }
                    pnlColorIndicator.BackColor = CostLineReport.ColorDisapprove;
                    break;
                case ApprovalState.Neutral:
                    foreach (Control c in pnlColorIndicator.Controls)
                    {
                        if (c is PictureBox)
                            ((PictureBox)c).BackColor = CostLineReport.ColorNeutral;
                    }
                    pnlColorIndicator.BackColor = CostLineReport.ColorNeutral;
                    break;
            }
        }
        private void ShowRecords(object sender, EventArgs e)
        {
            if (this._Costlinereportdata.Costline.LocalData != null)
            {
                using (Forms.frmCostlineRecords f = new Forms.frmCostlineRecords(this._Costlinereportdata.Costline.LocalData))
                {
                    f.ShowDialog();
                }
            }
            else
                MessageBox.Show("This line has no records associated to it. The detailed list cannot be shown.",
                                "Can't show form",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
        }
        private void SwitchCalculateState(object sender, EventArgs e)
        {
            if (this._Costlinereportdata.Calculationstate == CalculationState.Included)
            {
                this._Costlinereportdata.Calculationstate = CalculationState.Excluded;
                this.picCalculation.Image = CostLineReport.ImageCalculationExclude;
            }
            else
            {
                this._Costlinereportdata.Calculationstate = CalculationState.Included;
                this.picCalculation.Image = CostLineReport.ImageCalculationInclude;
            }
        }
        public void SetCalculateState(CalculationState st)
        {
            switch (st)
            {
                case CalculationState.Included:
                    this._Costlinereportdata.Calculationstate = CalculationState.Excluded;
                    break;
                case CalculationState.Excluded:
                    this._Costlinereportdata.Calculationstate = CalculationState.Included;
                    break;
            }
            this.SwitchCalculateState(this, null);
        }
        #endregion

        #region INTERFACE_IMEPLEMENTS
        void IDisposable.Dispose()
        {
            this._Costlinereportdata = null;
            this.picApprove.Image.Dispose();
            this.picCalculation.Image.Dispose();
            this.picCollapse.Image.Dispose();
            this.picDetail.Image.Dispose();
            this.picDisapprove.Image.Dispose();
            this.picViewRecords.Image.Dispose();
            this.rtDetail.Dispose();
            this.rtMainData.Dispose();
            this.lblDivider.Dispose();
            this.lblDivider2.Dispose();
            this.lblDivider3.Dispose();
            this.lblDivider4.Dispose();
            this.lblTextDivider.Dispose();
            this.lblTitle.Dispose();
            this.picApprove.Dispose();
            this.picCalculation.Dispose();
            this.picCollapse.Dispose();
            this.picDetail.Dispose();
            this.picDisapprove.Dispose();
            this.picViewRecords.Dispose();
            this.pnlColorIndicator.Dispose();
            ttpApprove.Dispose();
            ttpDisapprove.Dispose();
            ttpCollapse.Dispose();
            ttpDetail.Dispose();
            ttpViewRecords.Dispose();
            ttpCalculation.Dispose();
            base.Dispose(true);
        }
        #endregion
    }
}

Visuele inhoud van de user control:
Code:
CostLineReport - System.Windows.Forms.UserControl
-lblDivider - System.Windows.Forms.Label
-lblDivider2 - System.Windows.Forms.Label
-lblDivider3 - System.Windows.Forms.Label
-lblDivider4 - System.Windows.Forms.Label
-lblTextDivider - System.Windows.Forms.Label
-lblTitle - System.Windows.Forms.Label
-lblTopDivider - System.Windows.Forms.Label
-picApprove - System.Windows.Forms.PictureBox
-picCalculation - System.Windows.Forms.PictureBox
-picCollapse - System.Windows.Forms.PictureBox
-picDetail - System.Windows.Forms.PictureBox
-picDisapprove - System.Windows.Forms.PictureBox
-picViewRecords - System.Windows.Forms.PictureBox
-pnlColorIndicator - System.Windows.Forms.Panel
-rtDetail - System.Windows.Forms.RichTextBox
-rtMaindata - System.Windows.Forms.RichTextBox

Disposen van user controls op panel (gebeurt vlak voor dat er nieuwe op komen)
Code:
            while (pnlCenterRightControls.Controls.Count > 0)
            {
                pnlCenterRightControls.Controls[0].Dispose();
            }
            GC.Collect();

Aanmaken van nieuwe controls op 't panel
Deze heb ik erbij gezet omdat hier ook nog een method aan een event (picCalculation.Click) wordt gekoppeld
De ToControl roept returnt een nieuwe usercontrol en geeft zichzelf mee aan de Ctor.
Code:
foreach (Classes.CustomControls.CostLineReportData c in SelectedCostlineReports)
            {
                Classes.CustomControls.CostLineReport r = c.ToControl();
                r.CalculateControl.Click += delegate(object o, EventArgs e) { GetCostCalculation(); };
                this.pnlCenterRightControls.Controls.Add(r);
            }

Help! :D

ultddave

Legacy Member
Ik denk dat je dat best test door eerst een groot stuk code in commentaar te zetten => en dan via trial-en-error checken door steeds meer te uncommenten, te kijken wanneer hij minder objecten verwijderd dan dat hij er aanmaakt.

Dan weet je bij welke componenten de fout kan liggen, want ik zie het niet zo direct. Ik vind het wel vreemd dat je de Images disposed terwijl die als static gedefinieerd staan in die klasse? Waarom ga je die dan disposen:
Code:
            this.picApprove.Image.Dispose();
            this.picCalculation.Image.Dispose();
            this.picCollapse.Image.Dispose();
            this.picDetail.Image.Dispose();
            this.picDisapprove.Image.Dispose();
            this.picViewRecords.Image.Dispose();

Recipe4hate

Legacy Member
Je hebt gelijk dave, die images mogen niet gedisposed worden.
Die fout is dus rechtgezet, ik dispose enkel mijn pictureboxes.

Voor de rest heb ik redelijk wat hulp gekregen op stackoverflow en zijn we tot het probleem van de memoryleak gekomen:
de events op de controls behouden hun subscribers na het disposen.
Na het verwijderen van deze (event -= method), kom ik op een constant getal uit.

Voor de geïnteresseerden:
C# winforms possible memoryleak when adding and removing custom controls to flowlayoutpanel (many User objects in taskmanager) - Stack Overflow
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan