简体   繁体   English

处置未实现IDisposable的第三方类使用的资源

[英]Dispose of resources used by 3rd party class which does not implement IDisposable

I'm using a 3rd party assembly to provide sftp functionality to my project as shown below. 我正在使用第3方程序集为我的项目提供sftp功能,如下所示。 Multiple threads need to implement this functionality so the 3rd party assembly is consumed in a static helper class. 需要多个线程来实现此功能,因此第三方程序集在静态帮助器类中使用。

The 3rd party assembly works well unless an unusual error condition is encountered, eg the sftp server exists but the directory I'm attempting to put files into gets deleted. 除非遇到异常错误情况,例如,sftp服务器存在,但是我试图放入文件的目录被删除,第三方程序集才能很好地工作。 When this happens a valid exception is thrown however it appears that intermittently the 3rd part assembly isn't cleaning up after itself correctly as no new instances of the client will work. 当发生这种情况时,会抛出一个有效的异常,但是似乎间歇性地第三部件装配没有正确地对其自身进行清理,因为没有新的客户端实例可以工作。

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(); }
            }
        }
    }

I have no means to get the 3rd party assembly changed so what I'm looking for is a way to dispose of any resources it may have taken. 我没有办法更改第三方大会,因此我正在寻找一种处置可能占用的任何资源的方法。 However the 3rd party class being called does not implement IDisposable itself. 但是,被调用的第三方类本身并不实现IDisposable。

So.. I'm trying to figure out if its possible to release the resources used by the 3rd party ? 所以..我试图找出是否有可能释放第三者使用的资源?

The two possible approaches I can think of are either 我能想到的两种可能的方法是

1: add a wrapper class which has the 3rd party class as its base class & which also implements IDisposable (shown below) - however I'm pretty sure this won't clean up the base class 1:添加一个包装器类,该包装器类将第3方类作为其基类,并且还实现IDisposable(如下所示)-但是,我很确定这不会清除基类

2: use a WeakReference to the 3rd party class (shown below) - but I don't know if this will work 2:对第3方类使用WeakReference(如下所示)-但我不知道这是否可行

Wrapper Class 包装类

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

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

WeakReference WeakReference的

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(); }
            }
        }
    }

So the problem with the WeakReference is: 因此, WeakReference的问题是:

while still allowing that object to be reclaimed by garbage collection. 同时仍然允许垃圾回收回收该对象。

it doesn't guarantee that GC will get to it because it clearly isn't managing itself well internally. 它不能保证GC会成功,因为它显然在内部无法很好地进行自我管理。

The better approach is to base the class and implement IDisposable . 更好的方法是基于该类并实现IDisposable This will allow you to leverage your wrapper in a using statement. 这将允许您在using语句中利用包装器。 However, the caveat is this, and there's really no way around it, you're going to have to use Reflection to dig into this class and clean it up. 但是,需要注意的是,实际上没有办法解决,您将不得不使用Reflection来深入研究此类并进行清理。

It's going to take a lot of breakpoints, and a lot of digging in the Watch windows, but you can get it done! 这将需要很多断点,并且需要在Watch窗口中进行大量挖掘,但是您可以完成它!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM