如何仅在引用数为零时处置对象

时间:2017-01-30 09:44:26

标签: c# dispose

我有一个Director为线程提供构建器。 一旦事件被触发,我需要处理Builder,因为它拥有本机资源但是只有当所有线程完成时才会这样。

我将构建器保留在Cache中,因此如果Director发布了Builder,则可以将其视为Dispose引用数量为零。

我知道循环引用问题,并且它与此方案无关,因为只有Director提供引用。

我知道我应该实现FinalizeSuppressFinalize模式,以避免在处置Builder之前线程死亡时内存泄漏。

请考虑以下示例,其中很难分辨谁应该实际部署构建器:

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main()
        {
            var builderId = 1;
            var dictionary = new Dictionary<int, MyBuilder> {{builderId, new MyBuilder()}};

            var director = new Director(dictionary);
            for (var i =0 ; i < 5; i++)
            {
                new Worker(director.GetBuilder(builderId));
            }
            director.Dispose(builderId);

            Thread.Sleep(10000);
        }
    }

    public class Director
    {
        private readonly Dictionary<int, MyBuilder> _cache;

        public Director(Dictionary<int, MyBuilder> cache)
        {
            this._cache = cache;
        }

        public MyBuilder GetBuilder(int i)
        {
            MyBuilder builder;
            _cache.TryGetValue(i, out builder);
            return builder;
        }

        public void Dispose(int i)
        {
            MyBuilder builder;
            _cache.TryGetValue(i, out builder);
            builder?.Dispose();
        }
    }

    public class MyBuilder :IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Should I dispose?");
        }

        public void Build()
        {
            Console.WriteLine("Build");
        }
    }

    public class Worker
    {
        public void Work(MyBuilder builder)
        {
            builder.Build();
            builder.Dispose();
        }

        public Worker(MyBuilder builder)
        {
            var t = new Thread(() => Work(builder));
            t.Start();
        }
    }
}

0 个答案:

没有答案