2014-08-27 76 views
3

我发现了一些奇怪的代码在一个旧的项目我们的,这是看起来像这样:使用关键字+ Lambda表达式

using (var removeGroupMembershipWorker = new BackgroundWorker()) 
{ 
    removeGroupMembershipWorker.DoWork += (senderRGMW, eRGMW) => 
    { 

    }; 
    removeGroupMembershipWorker.RunWorkerAsync(); 
} 

在lambda的代码会被省略。

对于我来说,using关键字和lambda表达式不能很好地结合在一起:Lambda必须在类层次上利用该对象,否则代码将无法在以后调用。

但是using关键字是如何在这里工作的? Thread显然不会等待Async完成,但当using块剩下时会发生什么?

using在这种情况下是否被忽略?

伊迪丝说:因为我缺少拉古斯的答案和这个超级链接;我在这里添加它:http://softwareblog.alcedo.com/post/2011/12/09/Using-blocks-and-asynchronous-operations.aspx
这解释了有关该主题的问题和解决方案。

+0

你可以发表RunWorkerAsync()方法的正文吗? – Michael 2014-08-27 10:29:02

+0

Raghu写道,不需要感谢,这两个概念不能很好地协同工作 – 2014-08-27 11:06:00

+0

“使用”和lambda表达式之间的交互没有问题,这里的问题是由于异步,对象应该活得更长。所以lambda不是这里的问题,async nature + dispose是。 – 2014-09-02 07:29:32

回答

2

using块为try ... finally构建体,其中所述finally块调用对象的方法IDisposable.Dispose()语法糖。当然,这是为什么被丢弃的对象必须实现IDisposable,否则会出现编译时错误。

调用Dispose()与允许对象超出范围以垃圾收集不同。特别是,如果lambda中的代码恰好通过闭包来引用removeGroupMembershipWorker,则lambda可能最终引用已被处置的对象。这种情况可能会导致错误,也可能不会导致错误,具体取决于Dispose()的实际情况。

所以,正如你所说,using模式可能不是这里最好的主意。如果您确实需要致电Dispose() - 您确实应该为IDisposable做好准备 - 您可以在安全的情况下直接致电。 “安全的做法”意味着取决于你的代码,但实质上,Dispose()需要是对象上调用的最后一个方法(当然,除了在Dispose()内调用的任何方法)。

+0

说什么是最后一次调用通常是不可能的我会说,因为我们不知道异步方法的工作顺序。 如上所述,我认为确实有很少的对象是IDisposable和异步方法,Backgroundworker是我迄今唯一知道的。 奇怪的是,我错过了Raghu的评论,该评论有关于这个主题的非常好的链接。 – 2014-09-01 19:33:27

+0

@MatthiasMüller,在完成所有的异步操作之后,您不会想要调用Dispose(),这就是为什么'using'在这里可能无法正常工作的原因。有多种方式可以确定何时应该实际处理对象,但没有更多信息,我不知道该怎么建议。 – Andrew 2014-09-01 19:40:39

+0

流也有异步方法。 – 2014-09-02 06:23:23