C# WinForm 程序在关闭时,析构顺序,让我很糊涂

jmcooler 2016-09-29 06:56:05

class FlowProject
{
// 内存映射文件对象(作为数据库使用)
private mapFile;
}


如上,一个 FlowProject 类中,包含了一个内存映射文件对象,作为数据库使用。
FlowProject 被传递给了多个线程。

当用户,命令我删除 FlowProject,并删除与其相关的工程文件 和 数据库文件时,

显然,我不敢贸然将 FlowProject 进行 Dispose,因为它还在被多线程使用。我也不知道这些线程什么时候用完。
其中的数据库也一直打开着,不敢贸然关闭。不过,主线程,已经不再引用FlowProject 对象了。

于是,我依靠 FlowProject 的析构函数来真正删除工程文件和数据库文件。在 FlowProject 中,弄了个删除标记。
我希望先关闭 mapFile,然后再依序删除文件。但是,没等我去关闭数据库(mapFile),它却先析构了。

FlowProject 不是还在引用 mapFile 嘛,它咋就先析构了呢?

这种问题,发生在程序关闭的时候,mapFile 先于 FlowProject 析构。但是它也不是每次都先析构。

难道 C# 对象的析构,就那么随机,完全没有规律吗?

“继承”的对象,都可以按派生顺序析构,为何“组合”对象,却不是先析构外层对象,再析构内部组合的对象呢?

...全文
547 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
圣殿骑士18 2016-10-01
  • 打赏
  • 举报
回复
引用 3 楼 jmcooler 的回复:
我测试的时候,还未将 FlowProject 传给多线程。就是,界面删除该工程之后,关闭程序,来测试析构函数处理删除文件的逻辑。 如果,仅仅实在关闭程序时,析构顺序混乱,那还好了。 要是运行过程中析构顺序是乱的,那 C# 的引用和内存回收,岂不是不靠谱了。 我要去释放某个我引用的资源时,它却先析构(释放)了。 我还持有它的引用呢,它怎么能析构呢????
你持有它的引用,然而你本身也没有对象引用,所以你们两个都在释放的队列中,而框架只是没有对你们再进行释放的顺序排序而已。想想如果还要对释放顺序进行排序,那这个效率损失,是不值得的
圣殿骑士18 2016-10-01
  • 打赏
  • 举报
回复
我是飞云 2016-10-01
  • 打赏
  • 举报
回复
嗯,都基本上说到点上了 补充点,所谓的析构其实是一个不可靠的过程,特别是依赖GC机制,很可能不会被执行,甚至执行到一半就意外了,比如IIS暂停。因此应该尽量的减少在析构中去做一些关键性的维护,比如说更新数据。 应该考虑自己为什么需要用到析构,如何去做一个比较可靠的设计。 #4是大多数、也是“常规”的做法。
我是瓶起子 2016-09-30
  • 打赏
  • 举报
回复
主线程结束进程就结束了!可以在进程结束前等待子线程的过程结束同步结束
我是瓶起子 2016-09-30
  • 打赏
  • 举报
回复
函数执行完成后,函数线程中的变量就已经没有了,它所引用的堆中的对象就像无头尸一样等待gc来打扫
crystal_lz 2016-09-30
  • 打赏
  • 举报
回复
- -!..你的问题我没有仔细看 只看了一个大概 我以前也问过关于析构函数的问题 但是得到的回答是 这个东西 只是c++的一个遗留 到了。Net中并不靠谱 就好比垃圾回收一样 这一切都由框架来管理了 什么时候调用取决于 框架 反正别人是这样给我回答的
jmcooler 2016-09-29
  • 打赏
  • 举报
回复
我测试的时候,还未将 FlowProject 传给多线程。就是,界面删除该工程之后,关闭程序,来测试析构函数处理删除文件的逻辑。 如果,仅仅实在关闭程序时,析构顺序混乱,那还好了。 要是运行过程中析构顺序是乱的,那 C# 的引用和内存回收,岂不是不靠谱了。 我要去释放某个我引用的资源时,它却先析构(释放)了。 我还持有它的引用呢,它怎么能析构呢????
jmcooler 2016-09-29
  • 打赏
  • 举报
回复
你的思路很好,就是用引用计数,来应对多线程释放的问题,这是 C++ 的典型方案。 不过针对我这个问题,我已经想出了更好的办法来解决: 直接关闭 mapFile 数据库文件,关闭后,不允许读写。可以直接删除工程文件和数据库文件。 但是,我就是搞不懂,C# 的析构顺序咋这么乱。那析构函数是一点用都没有,就算是用来释放 资源,都要小心又小心,也许你引用的那个资源,早在本类析构之前,早已析构了。
crystal_lz 2016-09-29
  • 打赏
  • 举报
回复

class FlowProject : IDispose
{
    // 内存映射文件对象(作为数据库使用)
    private 【static】 mapFile;
    private static int m_nCount;
    
    private bool m_isDisposed;
    private object m_obj_sync = new object();
    
    public FlowProject(){
        lock(m_obj_sync)m_nCount++;
    }
    
    ~FlowProject(){
        this.Dispose();
    }
    
    public void Dispose(){
        if(m_isDisposed)return;
        lock(m_obj_sync){
            if(--m_nCount == 0){
                释放你的东西
                m_isDisposed = true;
            }
        }
    }
}

111,093

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧