我在我们的旧项目中发现了一些奇怪的代码,看起来像这样:
using (var removeGroupMembershipWorker = new BackgroundWorker())
{
removeGroupMembershipWorker.DoWork += (senderRGMW, eRGMW) =>
{
};
removeGroupMembershipWorker.RunWorkerAsync();
}
Lambda中的守则被删除了。
对我来说,using
关键字和lambda表达式不能很好地结合在一起:Lambda必须在类级别上利用该对象,否则以后无法调用该代码。
但using
关键字在这里如何运作?线程显然不等待异步完成,但是当using
块被遗留时会发生什么?
在这种情况下,using
是否被忽略了?
答案 0 :(得分:2)
using
块是try
... finally
构造的语法糖,其中finally
块调用对象的IDisposable.Dispose()
方法。当然,这就是为什么被处理的对象必须实现IDisposable
,否则会出现编译时错误。
调用Dispose()
与允许对象超出范围进行垃圾回收不同。特别是,如果lambda中的代码碰巧通过闭包引用removeGroupMembershipWorker
,则lambda最终可能会引用已被处置的对象。这种情况可能会或可能不会导致错误,具体取决于Dispose()
实际执行的操作。
所以,正如你所提到的,using
模式可能不是最好的主意。如果您确实需要致电Dispose()
- 您应该为任何IDisposable
致电 - 您可以在安全的情况下直接致电它。什么"安全这样做"意味着取决于你的代码,但实质上,Dispose()
需要是对象调用的最后一个方法(当然在Dispose()
内调用的任何方法除外)。