【问题标题】:Garbage collection too agressive in a Winforms projectWinforms 项目中的垃圾收集过于激进
【发布时间】:2013-11-15 12:43:18
【问题描述】:

我继承了一个 WinForms 项目并且遇到了一个奇怪的问题,我已将其缩小为 GC 问题。我根本看不出它怎么可能是其他任何东西,但请随时告诉我:-)

应用程序每隔几个月就会运行一次。我无法定期重现它,但它发生在我的客户身上几次,我在我的开发人员环境中看到过两次(但在我寻找它时从未见过)。

下面的代码简化了设置。

public class Main
{
  Main()
  {
    var listOfB = new List<ObjB>();
    var objB = new ObjB();
    listOfB.Add(objB);
    var objA = new ObjA(objB);

    // Do alot of stuff with listOfB and different lists of objA-like-objects.
    // Sometimes objA only exists as objects in a DataGrid

    // listOfB exists for a long time, while objA comes and goes..
  }
}

class ObjA
{
  private bool _isBNull;
  private ObjB _objB;

  public ObjA(ObjB objB)
  {
    _objB = objB;
    _isBNull = objB == null;
  }

  public ObjB ObjB
  {
    get
    {
      if (!_isBNull && _objB == null)
      {
        //
        // This should NEVER happen, but happens anyway :-(
        //

        // Do some logging and now that we 
        // know it CAN happen anyway we throw up...
      }
      return _objB;
    }
    set
    {
      _isBNull = value == null;
      _objB = value;
    }
  }
}

class ObjB
{
}

我们最终处于 objB 为空的应该不可能的情况,但我们的 debug-track-boolean 告诉我们它不应该是。

有没有人经历过这样的事情?关于做什么或去哪里看的任何建议?

项目是.Net 4.0,在32位XP和64位Windows 7客户端机器上都出现过这个错误。

Smøller - WinForm 新手

【问题讨论】:

    标签: c# .net winforms garbage-collection


    【解决方案1】:

    你的问题出在你的 setter 上,而不是在 gc 上:

    set
    {
      _isBNull = value == null;
      _objB = value;
    }
    

    setter/getter 不是线程安全的,如果您有多个线程同时访问 getter 和 setter,您可能会遇到 _isBNull == null 且 _objB 是对象的情况。

    在查看您当前的代码时,我认为没有任何理由拥有单独的属性 _isBNull,您为解决此问题而必须做出的更改实际上取决于您对类的功能要求。

    【讨论】:

    • 好点,但我 _isBNull 的唯一原因是确认该对象实际上是空的,而我预计它不是。据我所知,只有主线程在运行并在发生错误时访问属性...
    • @Smoller 但是应用程序中运行的其他线程理论上可以访问 ObjA 实例上的此属性吗?因为这看起来像一个 heisenbug,而且往往是线程安全问题......
    猜你喜欢
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    相关资源
    最近更新 更多