我正在异步调用sql命令的beingexecutereader方法,用户可以取消。当取消发生时,我取消了sqlcommand对象,这将终止sql server上正在执行的作业。
但是一旦我取消它,就会调用BeginExecute查询中指定的回调方法,并且在尝试调用endexecutequery时它会出错。 result.Iscompleted是真的,直到调用了endexecute查询,此时它变为false。
有没有办法在回调方法中检测到该命令被取消了?或者我必须跟踪那个......
感谢
答案 0 :(得分:8)
我已经删除并重新开始了我的整个答案:你偶然发现了一个相互矛盾的文档和警告的好例子......
根据.NET 2.0 MSDN Documentation for the SqlCommand.Cancel“取消方法不能用于取消挂起的异步操作。”但是,.NET 3.5的相同文档不包含此警告 - 尽管与2.0文档完全相同。
我建议遵循Calling Synchronous Methods Asynchronously中列出的约定为Delegate.BeginInvoke(不是Control.BeginInvoke!)和Delegate.EndInvoke的约定,但可能与您的情况有关。
名为“Begin ... Async”的方法返回IAsyncResult并具有相应的“End ...”方法,可能会产生ThreadPool泄漏。防止泄漏的最简单方法是确保始终调用相应的“End ...”方法。
原因是当调用Begin ... Async时,它从ThreadPool获取一个线程,并且(通常)在工作线程上执行该方法的同步版本;在您的情况下ExecuteReader()。该调用的返回值,或在该调用期间发生的任何异常,在调用End ...之前不会返回到主线程 - 如果您从未调用End,则永远不会返回结果/异常并且ThreadPool线程永远不会被释放。
长话短说,只要你确保调用EndExecuteReader()并处理预期的异常,你就很安全。由于文档是矛盾和模糊的,我已经开始discussion on the MSDN Feedback Forums。
答案 1 :(得分:2)
快速查看http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98217报告此行为的确切位置。
所以看起来你应该只捕获EndExecuteReader中抛出的这个特定异常并忽略它。