【问题标题】:Dispose of resources used by 3rd party class which does not implement IDisposable处置未实现 IDisposable 的第 3 方类使用的资源
【发布时间】:2013-08-02 13:19:09
【问题描述】:

我正在使用第 3 方程序集为我的项目提供 sftp 功能,如下所示。 多个线程需要实现此功能,因此第 3 方程序集在静态帮助程序类中使用。

除非遇到不寻常的错误情况,否则第 3 方程序集运行良好,例如sftp 服务器存在,但我试图将文件放入的目录被删除。 发生这种情况时会引发一个有效异常,但似乎第 3 部分组件间歇性地无法正确清理自身,因为没有新的客户端实例可以工作。

static readonly object _locker = new object();

    static void WorkerMethodCalledByThread()
    {
        lock(_locker)
        {
            var client = new ThirdPartyAssembly();
            bool hasConnection = false;
            try
            {
                client.Connect("some connection details");
                hasConnection = true;
                // do some work - 
                //but if an issue happens here then no new instances of ThirdPartAssembly work
            }
            catch(Exception e)
            {
                Logger.LogError(e);
            }
            finally
            {
                if (hasConnection) { client.Close(); }
            }
        }
    }

我没有办法改变第 3 方大会,所以我正在寻找一种方法来处理它可能占用的任何资源。然而,被调用的第 3 方类本身并没有实现 IDisposable。

所以.. 我想知道是否可以释放第 3 方使用的资源?

我能想到的两种可能的方法是

1:添加一个包装类,它以 3rd 方类作为其基类,并且还实现了 IDisposable(如下所示) - 但是我很确定这不会清理基类

2:对第 3 方类使用 Wea​​kReference(如下所示) - 但我不知道这是否可行

包装类

public class WrapperClass : ThirdPartyClass, IDisposable
{
    ~WrapperClass()
    {
        Dispose();
    }

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

弱引用

static readonly object _locker = new object();

    static void WorkerMethodCalledByThread()
    {
        lock(_locker)
        {
            var client = new WeakReference(new ThirdPartyAssembly());
            bool hasConnection = false;
            try
            {
                ((ThirdPartyAssembly)client.Target).Connect("some connection details");
                hasConnection = true;
                // do some work - 
                //but if an issue happens here then no new instances of ThirdPartAssembly work
            }
            catch(Exception e)
            {
                Logger.LogError(e);
            }
            finally
            {
                if (hasConnection) { ((ThirdPartyAssembly)client.Target).Close(); }
            }
        }
    }

【问题讨论】:

  • 如果第三方类有需要处理的内部资源,我不确定使用弱引用会有什么帮助,除非你的代码有内存泄漏问题并且是仍然指的是旧对象。如果您知道第三方库用于处理的内部资源/方法,则可以利用反射来获取这些私有成员以执行您自己的手动清理。
  • instanceOfThirdPartyClass = null;没用?

标签: c#


【解决方案1】:

所以WeakReference 的问题是:

同时仍然允许垃圾收集回收该对象。

它不能保证 GC 会处理它,因为它显然没有在内部很好地管理自己。

更好的方法是基类并实现IDisposable。这将允许您在 using 语句中利用您的包装器。但是,需要注意的是,真的没有办法绕过它,你将不得不使用Reflection 来挖掘这个类并清理它。

这需要很多断点,并且在Watch 窗口中进行大量挖掘,但您可以完成它!

【讨论】:

    猜你喜欢
    • 2012-03-17
    • 2011-03-02
    • 2013-09-29
    • 2023-03-08
    • 2012-11-10
    • 2013-10-29
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多