SqlCommand.BeginExecuteReader()报告存储过程实际完成之前的完成

时间:2020-10-13 08:16:42

标签: .net sql-server

我正在尝试实现一个监视长时间运行的SQL存储过程的过程。我的代码在执行存储过程的SqlCommand上调用BeginExecuteReader()。然后,我在循环中轮询IAsyncResult.IsCompleted值。在线所有文献都说,仅当存储过程完成执行时,IsCompleted才设置为true。 但是我发现它几乎立即将其标记为true,退出循环。然后,当我调用EndExecuteReader()时,线程将阻塞,因为存储过程仍在运行。

IAsyncResult是否存在一些已知问题。是否已按预期方式工作?

值得一提的是,所讨论的存储过程调用了许多子存储过程。这些消息均写入控制台窗口(我的代码通过InfoMessage事件提取这些消息)。但是,SP不会在IsCompleted正在标记的点返回结果集。

private static void runEtlLoadStoredProcedure(EtlState etlState, ConcurrentBag<EtlError> errors) {
        using (var executingUc = etlState.Context.CreateNewUserContext()) {     // Create a separate UserContext and SqlConnection so we can concurrently read and write to DB
            executingUc.SqlConn.InfoMessage += (sender, args) => SqlConn_InfoMessage(sender, args, etlState);       // Event handler when messages are generated by the ETL Stored Procedure
            using(SqlCommand command = new SqlCommand(EtlConfig.StagingToLiveStoredProcedure, executingUc.SqlConn) { CommandType = CommandType.StoredProcedure }) {
                var asyncResult = command.BeginExecuteReader();
                monitorUntilComplete(etlState, executingUc.SqlConn, command, asyncResult, errors);      // Will periodically check for cancellation, waiting until the SP call has finished
                using(SqlDataReader reader = command.EndExecuteReader(asyncResult)) {                   // Get any result sets returned by the ETL SP

                }
            }
        }
    }

private static void monitorUntilComplete(EtlState etlState, SqlConnection executingConn, SqlCommand sqlCommand, IAsyncResult asyncResult, ConcurrentBag<EtlError> errors) {
        while (!asyncResult.IsCompleted) {
            System.Threading.Thread.Sleep(EtlConfig.StagingToLivePollingIntervalMs);        // Wait for a period of time
            int x = 0;      // Test
            Debug.WriteLine("waiting");
        }
        int y = 1;
    }

更新

使用BeginExecuteNonQuery而不是Reader时,结果没有任何变化。当我删除SqlConnection.InfoMessage事件时,也没有任何变化。 切换到 ExecuteNonQueryAsync 可行;可以轮询Task对象,直到完成。但是,使用此函数时,不会触发SqlConnection.InfoMessage事件,因此这产生了一个新问题。

有人知道吗?

  1. SqlConnection.InfoMessage事件在哪个线程上运行?它们必须在工作线程上运行,因为它们可以在存储过程执行过程中随时触发?
  2. 为什么InfoMessage不触发?
  3. 是否还有其他方法可以访问SQL Server消息输出?请注意,输出消息是通过调用严重性为零和NOWAIT的RAISERROR在SQL端生成的。

0 个答案:

没有答案
相关问题