【问题标题】:Unhook Func Target取消挂钩功能目标
【发布时间】:2018-05-17 02:09:13
【问题描述】:

我有一个字节[]的字典,功能如下:

 public class ImageSizeReader : IDisposable
 {

    private Dictionary<byte[], Func<BinaryReader, Size>> imageFormatDecoders;

    public ImageSizeReader()
    {
        imageFormatDecoders = new Dictionary<byte[], Func<BinaryReader, Size>>()
        {
            { new byte[] { 0x42, 0x4D }, DecodeBitmap },
            { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif },
            { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif },
            { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng },
            { new byte[] { 0xff, 0xd8 }, DecodeJfif }};
    }

    private Size DecodeBitmap(BinaryReader binaryReader)
    {
    ....
    }

    private Size DecodeGif(BinaryReader binaryReader)
    {
        ...
    }

    private Size DecodePng(BinaryReader binaryReader)
    {
      ...
    }

    private Size DecodeJfif(BinaryReader binaryReader)
    {
       ...
    }

}

使用 Memory Profiler 后,我注意到此 Dictionary 阻止了对其父类进行垃圾收集:

我假设这是因为 Func 委托仍处于连接状态。我如何正确地“解开”这个委托列表?

【问题讨论】:

  • imageFormatDecoders 静态的吗?
  • 嗨@DanielA.White,我已经更新了代码示例。 imageFormatDecoders 是一个实例成员。
  • 顺便说一句,byte[] 是一个糟糕的字典键,除非你覆盖比较器,因为相等是基于引用相等。
  • 当然它使实例保持活动状态,但实例也是唯一保持字典活动的东西。它们形成一个循环,GC 知道如何处理它们。一旦对解码器的所有外部引用都被释放,它将是可收集的,因为它无法从 GC 根访问,而不是因为没有对它的引用。

标签: c# delegates func


【解决方案1】:

我回过头来,最终发现上图中的代码是编译器从 linq 语句生成的:

int maxMagicBytesLength = imageFormatDecoders.Keys.OrderByDescending(x => x.Length).First().Length;

我删除了这个方法,并在解决问题的 foreach 循环中做了同样的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 2015-10-20
    • 1970-01-01
    相关资源
    最近更新 更多