【发布时间】:2013-07-12 17:14:30
【问题描述】:
我正在研究 Microsoft 企业库(数据应用程序块)——示例 sln。
他们有一个异步读取数据的示例(IAsync,尽管新版本(6)也支持async)。
但是 Resharper(or 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 会调用。
那它为什么会大叫(警告)?
【问题讨论】:
-
旁白:为什么在等待结果时使用异步调用?似乎在这里使用
Tasks 会更直接。 -
样本 SLN。此 SLN 包含另外 15 个示例,这些示例也使用了 TASK(async)。不过,这不是我的问题。
-
我很好奇 - 是否存在这种情况的更简单变体,R# 足够聪明,可以将其识别为“安全”?如果是这样,我会感到惊讶。
-
我的猜测只是 R# 并不完美。它无法知道(即它的静态分析不够先进,无法了解事件如何与异步调用交互)在
using超出范围后从未调用过 lambda,因此它会警告您这可能会发生. -
@RoyiNamir 样本很可能是正确的。它可能是。 R# 试图阻止
event.Set()在using块完成后被调用。通过异步调用或 any 在 lambda 中使用该对象,这在理论上是可能的。该警告并不意味着“这是一个错误”,而是“这可能是一个错误,您应该更仔细地查看这段代码”
标签: c# .net multithreading