我正在调查Microsoft企业库(数据应用程序块) - 样本sln。
他们有一个异步读取数据的示例(IAsync
,尽管新版本(6)也支持async
)。
但Resharper(或visual studio- nevermind )向我展示:“访问处理关闭”:(首先我会显示图像,所以它会更清晰,然后我会粘贴代码)
代码:
/*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
将会调用。
那为什么会大喊(警告)?
答案 0 :(得分:64)
您将doneWaitingEvent
传递给可能超出使用块范围的lambda。即当lambda执行时,存在Dispose
被调用的风险。
答案 1 :(得分:52)
它会大声警告,因为引擎不够聪明,无法确定在委托代码完成之前永远不会退出using块。这就是为什么这是一个警告而不是错误。
你可以安全地忽略这个警告,你可以让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);
答案 2 :(得分:5)
你看到ReSharper警告的原因是ReSharper的代码流分析引擎不够强大,无法看到发生了什么:他们认为你的代码可以在没有using
的情况下到达doneWaitingEvent
子句的末尾被设置,由于while
循环而无法实现:
while (!doneWaitingEvent.WaitOne(1000)) {
Console.Write("Waiting... ");
}
循环将继续打印"Waiting... "
行,直到doneWaitingEvent.Set();
被调用,从而阻止您的代码到达using
块的末尾。另一个警告也是如此。
长话短说,这个警告可以安全地忽略。添加ReSharper的“忽略此警告”注释,并可选择向他们提交错误报告。