简体   繁体   English

线程内部的对象处置

[英]Object disposal inside the thread

I'm programming a plug-in for a large system. 我正在为大型系统编写插件。 The systems runs my plug-in in an independent thread. 系统在独立线程中运行我的插件。 Inside the plug-in I'm allocating an unmanaged resource. 在插件内部,我正在分配非托管资源。 I need to be 100% sure I release this driver. 我需要100%确定我释放此驱动程序。 I implemented the IDisposable pattern and I covered all methods the system claims to call if the plug-in is about to be terminated. 我实现了IDisposable模式,并涵盖了系统声称在插件即将终止时调用的所有方法。

I'm a bit worried about the situation, when the system for any reason quits my thread (Abort, or whatever). 当系统出于任何原因退出我的线程(中止或其他原因)时,我对此情况感到有些担心。 Could I do something more in my plug-in to ensure the unmanaged resource will be released? 我可以在插件中做更多事情以确保释放不受管资源吗?

Eg if I push stop debugging in VS, the resource remains unreleased (I know it's a stupid example). 例如,如果我在VS中停止调试,则资源仍未释放(我知道这是一个愚蠢的示例)。

Under .NET, there is no way to have code run when a thread terminates. 在.NET下,线程终止时无法运行代码。 The best you can do is write a finalizer, and hope it gets called within a reasonable time frame. 最好的办法是编写一个终结器,并希望在合理的时间范围内调用它。

You need to implement both a finalizer and IDisposable so that if for any reason Dispose is not called (thread abort), GC would release it. 您需要同时实现终结器和IDisposable以便如果由于某种原因未调用Dispose (线程中止),GC将释放它。

So your finalizer will call your Dispose method: 因此,终结器将调用Dispose方法:

class MyClass : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        // release ...
    }

    ~MyClass()
    {
        Dispose(false);
    }
}

Reason for passing disposing is that you know not to touch any state if it is finalizing. 通过处理的原因是,您知道如果状态即将完成,则不要触摸任何状态。

Try catching this exception: http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx 尝试捕获此异常: http : //msdn.microsoft.com/zh-cn/library/system.threading.threadabortexception.aspx

And do a disposing there if the resource has not been disposed. 如果尚未处理资源,请在那里进行处理。

This is actually a pretty confusing topic. 这实际上是一个令人困惑的话题。 One reason why we all harp about Thread.Abort is because it injects an asynchronous exception into the target thread. 我们都对Thread.Abort原因之一是因为它向目标线程注入了一个异步异常。 The injection is nondeterministic and can often be at an unsafe point. 注射是不确定的,通常可能处于不安全的位置。 It could occur immediately after acquiring a resource (lock, unmanaged resource, etc.) causing a resource leak or leaving a lock in an acquired state. 它可能在获取资源(锁,非托管资源等)导致资源泄漏或将锁保持在获取状态后立即发生。 The CLR has some provisions for mitigating the risk by attempting to delay the injection in some very intricate ways during the execution of try-catch-finally blocks. CLR具有一些规定,可以通过在try-catch-finally块的执行过程中尝试以某些非常复杂的方式延迟注入来减轻风险。 Unfortunately, there is no fail-safe way to guarentee all of the scenarios involved when calling Thread.Abort and I suspect the vast majoring of the edge cases lie in the unmanaged code realm. 不幸的是,在调用Thread.Abort时,没有一种确保所有涉及的情况的故障保护方法。我怀疑边缘情况的绝大多数是在非托管代码领域中。 For this reason I advise against aborting threads. 因此,我建议不要中止线程。

Instead your should design your plugin so that it runs in a separate AppDomain and accepts shutdown requests so that it has a chance to gracefully end on its own. 相反,您应该设计插件,以便它在单独的AppDomain运行并接受关闭请求,以便它有机会优雅地自行结束。 There would be some marginal level of protection by using a separate application domain since you could, as a last resort, abort a misbehaving thread and then tear down the AppDomain in which the thread was executing code. 通过使用单独的应用程序域,将有一定程度的保护级别,因为作为最后的选择,您可以中止行为异常的线程,然后拆除该线程正在执行代码的AppDomain Again, there is no guarentee that this will completely isolate the potential for corrupted state caused by the abort. 再次,没有保证这将完全隔离由中止引起的损坏状态的可能性。 The only fail-safe design is to run the plugin in its own process. 唯一的故障安全设计是在其自己的进程中运行插件。

Unrelated to the abort problem there a couple of things you need to do to make sure the unmanaged resource is released. 与中止问题无关,您需要做一些事情来确保释放非托管资源。 First, implement a finalizer so that in the absence of calling Dispose the finalizer should do it eventually. 首先,实现一个终结器,以便在没有调用Dispose的情况下最终实现该终结器。 Second, and I am not sure what level of protection this actually provides, call GC.SuppressFinalize after the call to the private Dispose(bool) method. 其次,我不确定此保护实际上提供了什么级别的保护,请在调用私有Dispose(bool)方法之后调用GC.SuppressFinalize If an ansynchronous exception were to get injected in the public Dispose method you do not want the object removed from the finalization queue. 如果要在公共Dispose方法中注入异步异常,则不希望将该对象从完成队列中删除。 Again, I am not sure how much that is going to help because your object may now be in a corrupted state which would prevent the second attempt at releasing the resource. 同样,我不确定会有什么帮助,因为您的对象现在可能处于损坏状态,这将阻止第二次尝试释放资源。 Third, if possible use one of the CriticalFinalizerObject or SafeHandle classes to wrap the resource as this adds further protection through the use of Constrained Execution Regions . 第三,如果可能,请使用CriticalFinalizerObjectSafeHandle类之一包装资源,因为这可以通过使用约束执行区域来进一步保护。

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

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