0

我有一个我认为最终用户运行存储过程的简单程序,它可能需要相当长的时间才能运行。我想我可以使用异步连接,调用 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);
4

1 回答 1

0

如果您使用 BeginExecuteNonQuery 您的代码在继续之前不会等待查询执行...它将标记为异步调用已完成。

如您所说,一种替代方法是使用单独的 BackGroundWorker 来执行存储过程,如果您希望它在后台线程中执行。

参考这个

于 2015-03-29T03:17:14.620 回答