在 C# 中访问已处理的闭包?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17620430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Access to disposed closure in C#?
提问by Royi Namir
I'm investigating Microsoft enterprise library (data application block) -- The samples sln.
我正在调查 Microsoft 企业库(数据应用程序块)——样本 sln。
They have a sample of reading data asynchronously ( IAsync, although the new ver (6) also support async).
他们有一个异步读取数据的示例(IAsync尽管新版本 (6) 也支持async)。
But Resharper(or visual studio- nevermind) shows me : "Access to disposed closure" : (first i will show the image , so it will be clearer , then i'll paste the code )
但是 Resharper(或visual studio-没关系)向我展示:“访问已处理的关闭”:(首先我将显示图像,这样它会更清晰,然后我将粘贴代码)


code :
代码 :
/*1*/ [Description("Execute a command that retrieves data asynchronously")]
/*2*/ static void ReadDataAsynchronously()
/*3*/ {
/*4*/ if (!SupportsAsync(asyncDB)) return;
/*5*/
/*6*/ using(var doneWaitingEvent = new ManualResetEvent(false))
/*7*/ using(var readCompleteEvent = new ManualResetEvent(false))
/*8*/ {
/*9*/ try
/*10*/ {
/*11*/ // Create command to execute stored procedure and add parameters
/*12*/ DbCommand cmd = asyncDB.GetStoredProcCommand("ListOrdersSlowly");
/*13*/ asyncDB.AddInParameter(cmd, "state", DbType.String, "Colorado");
/*14*/ asyncDB.AddInParameter(cmd, "status", DbType.String, "DRAFT");
/*15*/ // Execute the query asynchronously specifying the command and the
/*16*/ // expression to execute when the data access process completes.
/*17*/ asyncDB.BeginExecuteReader(cmd,
/*18*/ asyncResult = >
/*19*/ {
/*20*/ // Lambda expression executed when the data access completes.
/*21*/ doneWaitingEvent.Set();
/*22*/ try
/*23*/ {
/*24*/ using(IDataReader reader = asyncDB.EndExecuteReader(asyncResult))
/*25*/ {
/*26*/ Console.WriteLine();
/*27*/ Console.WriteLine();
/*28*/ DisplayRowValues(reader);
/*29*/ }
/*30*/ }
/*31*/ catch (Exception ex)
/*32*/ {
/*33*/ Console.WriteLine("Error after data access completed: {0}", ex.Message);
/*34*/ }
/*35*/ finally
/*36*/ {
/*37*/ readCompleteEvent.Set();
/*38*/ }
/*39*/ }, null);
/*40*/
/*41*/ // Display waiting messages to indicate executing asynchronouly
/*42*/ while (!doneWaitingEvent.WaitOne(1000))
/*43*/ {
/*44*/ Console.Write("Waiting... ");
/*45*/ }
/*46*/
/*47*/ // Allow async thread to write results before displaying "continue" prompt
/*48*/ readCompleteEvent.WaitOne();
/*49*/ }
/*50*/ catch (Exception ex)
/*51*/ {
/*52*/ Console.WriteLine("Error while starting data access: {0}", ex.Message);
/*53*/ }
/*54*/ }
/*55*/ }
Question :
题 :
Why is it giving this warning ? there is a manualreset-checked-signal(which runs in a loop) which preventsthe usingclause to be reached - which means - no disposewill call .
为什么会发出这个警告?有一个manualreset-checked-signal(在循环中运行)阻止到达using子句 - 这意味着 - no disposewill call 。
So why does it yell (warning) ?
那么为什么它会大喊(警告)?
采纳答案by Brian Rasmussen
You pass doneWaitingEventto a lambda that may extend beyond the scope of the using block. I.e. there's a risk that Disposewill have been called when the lambda executes.
您传递doneWaitingEvent给可能超出 using 块范围的 lambda。也就是说,Dispose当 lambda 执行时,存在被调用的风险。
回答by Scott Chamberlain
It yells warning because the engine is not smart enough to figure out that the using block will never be exited before the delegate code completes. That is why this is a warning not a error.
它发出警告是因为引擎不够聪明,无法确定在委托代码完成之前永远不会退出 using 块。这就是为什么这是警告而不是错误的原因。
You can safely ignore this warning, you can have resharper suppress the warning by wrapping the lines with special comments
您可以安全地忽略此警告,您可以让 resharper 通过用特殊注释包装行来抑制警告
asyncDB.BeginExecuteReader(cmd, asyncResult =>
{
// Lambda expression executed when the data access completes.
// ReSharper disable AccessToDisposedClosure
doneWaitingEvent.Set();
// ReSharper restore AccessToDisposedClosure
try
{
using (IDataReader reader = asyncDB.EndExecuteReader(asyncResult))
{
Console.WriteLine();
Console.WriteLine();
DisplayRowValues(reader);
}
}
catch (Exception ex)
{
Console.WriteLine("Error after data access completed: {0}", ex.Message);
}
finally
{
// ReSharper disable AccessToDisposedClosure
readCompleteEvent.Set();
// ReSharper restore AccessToDisposedClosure
}
}, null);
回答by dasblinkenlight
The reason you see ReSharper's warnings is that ReSharper's code flow analysis engine is not strong enough to see what is going on: they assume that your code could get to the end of the usingclause without doneWaitingEventbeing set, which is not possible due to a whileloop:
您看到 ReSharper 的警告的原因是 ReSharper 的代码流分析引擎不够强大,无法查看正在发生的事情:他们假设您的代码可以在using没有doneWaitingEvent设置的情况下到达子句的末尾,这是不可能的,因为while循环:
while (!doneWaitingEvent.WaitOne(1000)) {
Console.Write("Waiting... ");
}
The loop will keep printing the "Waiting... "line until doneWaitingEvent.Set();gets called, preventing your code from reaching the end of the usingblock. Same goes for the other warning.
循环将继续打印该"Waiting... "行直到doneWaitingEvent.Set();被调用,从而防止您的代码到达using块的末尾。其他警告也是如此。
Long story short, this warning can be safely ignored. Add ReSharper's "ignore this warning" comments, and optionally file a bug report with them.
长话短说,可以安全地忽略此警告。添加 ReSharper 的“忽略此警告”注释,并可选择向其提交错误报告。

