【问题标题】:Destroying the form [closed]销毁表格[关闭]
【发布时间】:2013-12-02 18:11:48
【问题描述】:

我该怎么做?

破坏我的意思是从内存中删除它

一个例子(Form1 是某种形式):

static void Main()
{
    Test();
    // here we still have A alive
    // GC.Collect()  doesn't helps

    Form1 B = new Form1();
    Application.Run(B);
    // problem is here: B and A "collides", due to assumption what A is already dead
}

public static Test()
{
    Form1 A = new Form1();
    // do something with A, but not displaying form
    // I was sure what A will disappears after Test()
}

问题可能出在表单上使用的某些组件上吗?计时器,在构造函数中创建?还是 A 存在那么久的正常方式?

更新

碰撞 - 意味着他们正在使用仅供单个用户使用的东西。如何push从内存中删除 A 的过程?

请不要着急(感谢-2),我在工作,所以不能快速更新。我尽量说清楚。

只要可以,请避免使用陈词滥调GC.Collect 总是不好的,等等。我知道。正如您所看到的,我需要在软件运行之前对表单进行某种操作,因此预计不会出现性能或任何其他类型的问题。这可能不是最好的情况,但请告诉我更好的情况。对 A 做某事是必要的测试,是的。

问题是:在对 A 进行测试后,我希望它消失。当然,我可以修改 A 的方式,使其没有计时器、组件等。但是已经有几十种形式了。一切都必须经过测试。而且我根本不知道在 Test() 之后 A 会存在什么。

更新 2

我真的很想知道为什么 question 有 -3。我今天学到的是当你创建一个表单时,它会一直存在到应用程序结束,现在有已知的方法可以杀死它。在构造函数中创建的计时器将继续运行,组件将尝试访问它们不应该访问的东西,等等。只要您愿意创建工作(看起来)表单的第二个实例,很多事情都会发生变化。

更新 3

让我们做一个简单的测试:

static class Program
{
    public static bool Test { get; set; }
    static void Main()
    {
        DoTest();
        Test = true;
        Application.Run(new Form1());
    }

    static void DoTest()
    {
        var A = new Form1();
        var B = new Form1();
        var C = new Form1();
        //A.Dispose();
        //B.Dispose();
        //C.Dispose();
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (Program.Test)
        {
            timer1.Stop();
            MessageBox.Show("123");
        }
    }
}

它将显示 4 个消息框(来自主窗口和来自 undead A、B、C)。在今天之前,我百分百确定,我在表格上写的任何东西都会和表格一起被删除。每当我创建一个局部变量时——它将是局部的。但似乎并非如此。这是一个问题 - 不明显的行为。

看起来Dispose() 的 Thorsten Dittmar 解决方案应该可以解决问题。我应该检查自己的组件(手动关闭它们的计时器等)。

【问题讨论】:

  • B and A "collides"是什么意思
  • 你能定义“碰撞”吗?表格 A 将保留在内存中,直到 GC 另有决定。如果你有很多内存,这可能需要几天......
  • 在创建第一个 Form 时会发生很多疯狂的事情。对A 的多次引用被保存在winforms 代码的某个深处,我一点也不感到惊讶。我建议你找到一种不同的方式来做你想做的任何事情。也许如果你告诉我们那是什么,你会得到更好的答案。
  • GC.Collect() 几乎总是一个错误。
  • 顺便说一句。如果您在不显示表单 A 的情况下执行某些操作,然后运行 ​​Application.Run(B),那么您将遇到严重的设计问题。或者这只是某种测试?

标签: c# winforms garbage-collection destructor


【解决方案1】:

您应该致电Dispose()。即使这并不意味着所有内存都会立即被释放,如果表单编程正确,那么表单打开的所有资源(计时器、文件等)也应该关闭。

当然,表单也会在下次 GC 运行时自动销毁,但您可以自己调用Dispose() 手动使其“消失”。然后GC会在想运行的时候运行并照顾内存,但是应该释放窗口占用的其他资源。

最简单的方法是:

public static Test() {
    using (Form1 A = new Form1()) {
        // do something with A, but not displaying form
        // I was sure what A will disappears after Test() 
    }
}

【讨论】:

  • 我尝试调用A.Dispose(),但现在一些测试方法以FindForm().Handle 失败(因为FindForm() 返回null),计时器仍在继续运行,B 与A 发生碰撞。
  • 目前看来,唯一正确的解决方案是重新设计所有表单(这样它们就不会创建计时器,也不会尝试做其他事情)。如果我从一开始就知道 >
  • 也许你在错误的地方打电话给Dispose?此外,除非您使用Show 请求显示表单句柄,否则可能不会创建表单句柄。
  • 唯一的答案,但似乎是在正确的方向。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 1970-01-01
  • 2017-05-01
  • 2014-03-08
  • 2021-12-08
  • 2013-06-17
  • 1970-01-01
相关资源
最近更新 更多