我有一个我认为最终用户运行存储过程的简单程序,它可能需要相当长的时间才能运行。我想我可以使用异步连接,调用 Begin/EndExecuteNonQuery,并有一个计时器让用户知道它仍在运行。到目前为止,一切都很好。
如果某个参数为真,则被调用的存储过程将在最后执行另一个存储过程。看起来,当这个辅助调用发生时,IsCompleted 变为“真”,即使它不是,然后程序在 EndExecuteNonQuery 上阻塞,直到第二个 SP 完成。虽然我不确定,但我想这是因为直接的 SQL 进程完成了(因为它没有什么可做的,EXEC 调用是最后一行)但是一个子进程使调用继续进行。
如何判断 SP 是否完全完成?我知道我没有完全理解IAsyncResult.IsCompleted;我的印象是,true
当通话完全完成时,它就变成了,但该链接中的以下声明让我不这么认为:
当此属性为真时,您可以假定丢弃您分配给异步操作使用的任何资源是安全的。
所以它可能按预期工作,因为我可以安全地丢弃资源,即使完整的 SP 实际上并没有完成。如果是这种情况,是否有其他方法可以知道何时完成?我考虑过只ExecuteNonQuery
在另一个线程中使用法线(BackgroundWorker
?),但我想确保我没有首先丢失BeginXxx
/的东西EndXxx
。
我也愿意放弃 SqlCommand 这样程序就可以退出而无需等待 SP,因为第一个 SP 对最终用户来说是唯一真正重要的事情。
使用 .Net 4、MSSQL 2008 R2。
相关代码:
conn = new SqlConnection(@"Server=SERVERSQL;Initial Catalog=MyDatabase;User ID=MyUser;Asynchronous Processing=true");
SqlCommand cmd = new SqlCommand("OuterProcedure", conn);
cmd.CommandType = CommandType.StoredProcedure;
//[...]
IAsyncResult asyncObj = cmd.BeginExecuteNonQuery();
int count = 0;
int finalLine = Console.CursorTop;
while (!asyncObj.IsCompleted) {
Console.SetCursorPosition(0, finalLine);
++count;
Console.WriteLine("Time taken (m:s): {0}:{1}", Math.Floor((double)count / 60), (count % 60).ToString("D2"));
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Complete");
int results = cmd.EndExecuteNonQuery(asyncObj);