1

有没有办法可以从 Dispose 方法中取消处理,换句话说,在调用 A.Dispose() 时不处理 A。

更新 我没有很好地解释,因为我想不出一种很好的表达方式。我所拥有的是一个在单独线程中运行的弹出窗口中显示进度条(选取框)的类。当创建进度弹窗时,会返回一个类似控制器的一次性对象,所以我们可以这样做:

using (var progress = Dialogs.ShowProgress("Please wait..."))
{
    // do lots of stuff here
    progress.UpdateStatus("Please wait some more...");
    // do more stuff
}

当 using 块退出时,进度窗口将关闭并销毁。

现在我遇到这样的情况,在这个块中发生的事情也创建了一个进度窗口,而不是返回一个新对象并创建一个新窗口,我想返回第一个实例创建的对象,并且只有在第一个实例处理后才销毁它.

更新 好的,我所做的是在每次Dialogs.ShowProgress()调用时创建一个新的 IDisposable 对象,并将原始控制器对象附加到它上面。这些对象一旦完成就会被处理掉,而控制器只有在它是唯一需要处理的对象时才会被处理掉。

4

5 回答 5

4

正如其他人所说,以IDisposable一种可能不会真正处置的方式实施是一个坏主意。这是实现您要执行的操作的另一种方法:

interface IMaybeDisposable
{
    bool TryDispose(); //return false if dispose was canceled
}

你可以像这样使用它:

IMaybeDisposable maybe = //something
try
{
    // do something with maybe
}
finally
{
    if (maybe.TryDispose())
        // yay, it disposed!
    else
        // hm, it didn't dispose; do something else
}
于 2013-03-20T19:33:28.230 回答
1

所需的后置条件Dispose是客户端代码应该能够放弃对对象的所有引用,而不会导致任何必要的清理未完成。如果该条件在Dispose被调用之前适用,则该Dispose方法可能不会合法地执行任何操作。如果该条件不适用,Dispose则必须使其这样做,并且可能不会合法返回,除非或直到它这样做[注意,Dispose不需要实际执行清理,如果它启动了一系列事件,清理将在某些时候发生晚点]。接口合同中的任何内容都Dispose不允许它有时将对象置于需要进一步清理的状态,除非它有理由相信清理将通过其他方式进行。

于 2013-03-20T19:40:19.670 回答
1

当然。只是不要做任何你会做的事情来处理对象。你不需要积极地做任何特别的事情。

不过要小心;当有人处理一个对象时,他们希望它实际处理它的非托管资源,而不是无视你并无论如何都持有它们。

于 2013-03-20T19:23:14.600 回答
1

我会小心这样做。如果您在 using 块的末尾取消处置方法,那么您将丢失对该对象的引用,并且您将永远没有机会再次处置其内容,这意味着您可能会泄漏资源不小心。特别是,如果 dispose 方法释放了对我不希望出于任何原因立即收集垃圾的大对象的引用,我只会自己执行此操作。我不会这样做来跳过释放文件、数据库连接、网络套接字或其他任何不能被垃圾收集的句柄。

正如评论者指出的那样,我会尝试重构我的代码,以便我试图通过取消 dispose 来解决的任何问题都可以通过其他不那么危险的方式来解决。

如果你绝对确定你有一个边缘条件,你需要跳过处理某些东西,这是一种方法:

public void Dispose()
{
     if(condition)
     {
         // do disposing stuff
     }
}
于 2013-03-20T19:25:06.297 回答
0

根据您的更新,我会做这样的事情:

 public  void  DoStuff()
{
     DoPrepWork();
     using( var  controller =  TheMethodYouWroteThatShouldReturnAController())
    {
         DoStuffOverControllerLifetime();
    }
}
于 2013-03-20T19:54:33.827 回答