在C#中访问处理的封闭?

我正在调查微软企业库(数据应用程序块) – 样本sln。

他们有一个读取数据的asynchronous示例( IAsync ,虽然新版本(6)也支持async )。

但是Resharper( 或者Visual Studio- Nevermind )告诉我:“访问处理的closures”:(首先我将显示图像,所以它会更清晰,然后我将粘贴代码)

在这里输入图像说明

代码:

 /*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*/ } 

题 :

为什么会发出这个警告? 有一个manualreset-checked-signal (运行在一个循环中), 防止 using子句到达 – 这意味着 – 不dispose将调用。

那么为什么会大叫(警告)呢?

您将doneWaitingEvent传递给可能超出使用块范围的lambdaexpression式。 也就是说,执行lambda时有Dispose被调用的风险。

它大声警告,因为引擎不够聪明,以至于在委托代码完成之前永远不会退出使用块。 这就是为什么这是一个警告,而不是一个错误。

你可以放心地忽略这个警告,你可以通过包装特殊注释的行来抑制警告

  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); 

您看到ReSharper的警告的原因是ReSharper的代码stream分析引擎不够强大,看不到发生了什么事情:他们认为您的代码可能会在未设置doneWaitingEvent情况下doneWaitingEvent using子句的doneWaitingEvent ,这是不可能的,因为while循环:

 while (!doneWaitingEvent.WaitOne(1000)) { Console.Write("Waiting... "); } 

循环将继续打印"Waiting... "行,直到doneWaitingEvent.Set(); 被调用,阻止你的代码到达using块的末尾。 另一个警告也一样。

长话短说,这个警告可以安全地忽略。 添加ReSharper的“忽略这个警告”的意见,并可select提交一份错误报告。