【问题标题】:Finalizer is not called when console is closed关闭控制台时不调用终结器
【发布时间】:2013-08-12 16:50:37
【问题描述】:

在同时打开 Windows 窗体和控制台的 C# 应用程序中,为什么在关闭 From 时调用终结器,但在关闭控制台时不调用?即使从控制台关闭应用程序,是否有任何方法可以调用终结器?

我在创建一个在Construction上创建文件并在Dispose / Finalize上删除文件的类时注意到了这一点。关闭表单时它按预期工作,但关闭控制台时正在创建文件但未删除文件。

编辑

我一定对这些条款感到困惑。这是我的临时文件代码:

class TemporaryFile : IDisposable {
    private String _FullPath;

    public String FullPath {
        get {
            return _FullPath;
        }
        private set {
            _FullPath = value;
        }
    }

    public TemporaryFile() {
        FullPath = NewTemporaryFilePath();
    }

    ~TemporaryFile() {
        Dispose(false);
    }

    private String NewTemporaryFilePath() {
        const int TRY_TIMES = 5; // --- try 5 times to create a file

        FileStream tempFile = null;
        String tempPath = Path.GetTempPath();
        String tempName = Path.GetTempFileName();

        String fullFilePath = Path.Combine(tempPath, tempName);
            try {
                tempFile = System.IO.File.Create(fullFilePath);
                break;
            }
            catch(Exception) { // --- might fail if file path is already in use.
                return null;
            }
        }

        String newTempFile = tempFile.Name;
        tempFile.Close();

        return newTempFile;        
    }

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool calledFromDispose) {
        DeleteFile();
    }

    public void DeleteFile() {
        try {
            System.IO.File.Delete(FullPath);
        } catch(Exception) { } //Best effort.
    }
}

【问题讨论】:

  • 不要在 C# 中使用终结器。这是一个古老的概念。正确使用 IDisposable
  • 没有示例代码/异常细节,这从未发生过......
  • 你如何安排调用 Dispose() ?你做错了什么。
  • 课程似乎没问题,我敢打赌你没有使用using,也不要在你的应用程序中调用Dispose。您不能依赖终结器,它们完全有权不运行(尤其是在短期控制台应用程序中)。您必须使用Dispose(直接或通过using)。
  • @SoulDZIN - 您可以尝试禁用关闭按钮,以防止自己意外关闭它。 stackoverflow.com/questions/6052992/…

标签: c#


【解决方案1】:

问题不在于您的代码本身。

当您通过单击窗口中的 x 关闭控制台应用程序时,Windows 只会终止该进程。它不会优雅地关闭它,因此不会调用任何清理代码。

可以挂接到控制台 API 并捕获关闭处理程序,然后手动处理您的对象,但有报告称此功能在较新版本的 Windows 下无法很好地工作。

Capture console exit C#

【讨论】:

  • 我有点怀疑这一点,所以我可能会隐藏控制台。在那种情况下,如果操作系统试图终止进程,有没有办法捕捉到?我计划将大量数据放入临时文件中,如果用户不得不提前结束进程或其他原因,如果用户永远不会删除这些数据,那将是不可取的。
  • @SoulDZIN: this 必须帮忙。
  • @Vlad - 不。如果应用程序被强制终止,该事件也不会被调用。这只在正常关闭期间被调用。
  • @Mystere Man:好吧,如果应用程序通过任务管理器关闭,就没有办法拦截了,对吧?所以我们可以忽略它。我认为 OP 只是意味着“关闭窗口”说“试图终止进程”。但是如果操作系统强行终止进程,当然没有合法的途径。
  • @Vlad - 他的意思是单击 Windows 控制台窗口中的关闭框,它(理论上)会向应用程序发送一些 Win32 信号,如果忽略它与在任务中杀死它的作用相同经理。但是,Windows 7+ 在正确捕捉这些信号方面显然存在问题。这可能与他们实施的防碎修复有关。
猜你喜欢
  • 2012-06-16
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
相关资源
最近更新 更多