System.OutOfMemoryException:创建窗口句柄时发生错误。

3
我正在编写一个中等规模的WinForms应用程序……时不时会在创建某些窗体时出现此异常。
以前我曾经解决过这个问题,但并没有理解到底发生了什么。
令人困惑的是,昨天当我完成这个表单并测试它时,一切都运行得很好,现在我却遇到了以下错误:
未处理的类型为“System.OutOfMemoryException”的异常在System.Windows.Forms.dll中发生。 附加信息:创建窗口句柄时出错。
异常是在此代码块中抛出的:
    public partial class PonovniIspisRacunaForm : Form
        {    

        DataTable dnevniPrometTable;
        DataTable kontrolnaTrakaTable;
        DataTable ukupniDnevniPrometTable;
        DataTable stavkeRacunaTable;
        ZisCode.Hibernate.Mdb.DataModel dnevniPrometDataModel;
        ZisCode.Hibernate.Mdb.DataModel kontrolnaTrakaDataModel;
        OsnovniPodaci.Porezi.Stope stope;
        string brojRacuna;
        string ZKI;
        string JIR;
        string Operator;
        //decimal ukupno = 0.00m;

        decimal tarifa;
        decimal kolicina;
        decimal iznos;
        decimal porez;
        decimal porez25;
        decimal porez05;
        decimal porez13;
        decimal povratnaUkupno;
        decimal osnov25;
        decimal osnov05;
        decimal osnov13;
        //decimal nabavna; 

        PrintDocument printDocument;

        public PonovniIspisRacunaForm()
        {
            InitializeComponent();
        }

    private void FinancijskiRekapitular_Load(object sender, EventArgs e)
            {
                stope = new OsnovniPodaci.Porezi.Stope();

                // popunjava današnji datum
                this.dtpDatum.Value = DateTime.Today;

                // Get Data Table za određeni datum:
                dnevniPrometDataModel = ZisCode.DataModels.Get("DnevniPromet");
                kontrolnaTrakaDataModel = ZisCode.DataModels.Get("KontrolnaTraka");

                PrintSetup();

                ukupniDnevniPrometTable = MergeDnevniKontrolna();
                if (ukupniDnevniPrometTable.Rows.Count != 0)
                {
                    FillComboBox();
            }
        }
    private void FillComboBox()
            {
                cbBrojRacuna.DataSource = ZisCode.Methods.DataTableOperations.SortDataTable(ukupniDnevniPrometTable, "Dokument", "DESC") // orderbydescending
                    .AsEnumerable().GroupBy(row => row.Field<string>("Dokument")).Select(group => group.First()).CopyToDataTable(); // groupby brojRacuna-Dokument
                cbBrojRacuna.DisplayMember = "Dokument"; // Broj Računa
                cbBrojRacuna.ValueMember = "Dokument";
                cbBrojRacuna.SelectedIndex = 0;
            }

            private void PrintSetup()
            {
                // priprema za ispis
                printDocument = new PrintDocument();
                printDocument.DefaultPageSettings.PaperSize = new PaperSize("Racun size", 295, 500);
                printDocument.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(CreateRekapitular);
                // uklanja poruku dialog box (printing ..) kod ispisa
                PrintController printController = new StandardPrintController();
                printDocument.PrintController = printController;
                // popravlja font
                printPreview.UseAntiAlias = true;
            }
}

更具体地说,这一行代码:this.dtpDatum.Value = DateTime.Today; 为什么?我不知道为什么会出现异常...

我尝试在构造函数中设置dateTimePicker,但出现了与窗口句柄无关的不同异常。

我已经阅读了其他问题中的相关内容,但对我来说都没有太多帮助。

Winforms issue - Error creating window handle

Error Creating Window Handle

这两个答案对我没有帮助,因为它们的回答过于含糊,并且期望我首先了解dispose应该如何工作。请帮帮我,我是一个n00b!

更新:按要求发布了该类的几乎所有代码。


你能添加一些关于PrintSetup和FillComboBox()的代码吗?你有一些通用变量吗?在关闭表单时你会做什么? - Wai Fung Au Yeung
@WaiFungAuYeung 是的,我有很多变量,并且在关闭表单时我没有释放它们,哈哈,我该怎么做呢?尽管加载表单时会抛出这个异常。 - solujic
我已更新问题,并添加了更多的代码。 - solujic
3个回答

4
一个窗口句柄是一个未经管理的资源。它们的数量是有限的。如果您不释放这些句柄,Windows 将会用尽所有的资源并且您将会收到异常。
使用本机 HANDLE 的类需要在不再需要它们时释放它们。这些类将实现 IDisposable 接口。你应该研究一下,这是.NET的核心部分,对于处理像句柄这样的未经管理的资源至关重要。
打开静态代码分析(右键单击 项目 -> 属性 -> 代码分析 并选择 启用生成,然后选择 Microsoft 所有规则),并修复所有违规情况,特别是那些未被释放的 IDisposable

nvoigt,谢谢您的回复,我甚至不知道这个选项的存在 - 现在感觉自己像个大菜鸟... - solujic

1

由于您的异常是OutOfMemory,可能是因为您的内存不足。请检查任务管理器以查看可用内存量,并建议通过一些内存分析工具(如RedGate或类似工具)运行您的应用程序以查看泄漏位置。对于dispose,请参考此答案了解更多信息 C# Form.Close vs Form.Dispose


1
我不认为那是问题,可能是因为dateTimePicker没有被处理(?!),因为它是一个自定义用户控件...我不确定,只是猜测,因为dtp是异常的来源。 - solujic

0

问题出在私有的void

dtpDatum_TextChanged(object sender, EventArgs e)
{
    ukupniDnevniPrometTable = MergeDnevniKontrolna();
    FillComboBox();
}

我猜测这个事件被触发了太多次,导致了内存泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接