Хранимая процедура не выполнена, но IAsyncResult.IsCompleted имеет значение true

У меня есть то, что, как я думал, будет простой программой для конечных пользователей для запуска хранимой процедуры, выполнение которой может занять довольно много времени. Я думал, что смогу использовать асинхронное соединение, вызывать Begin/EndExecuteNonQuery и иметь таймер, который сообщит пользователю, что он все еще работает. Все идет нормально.

Если определенный параметр имеет значение true, вызываемая хранимая процедура будет исполнять другую хранимую процедуру в самом конце. Похоже, что когда происходит этот вторичный вызов, IsCompleted становится «истинным», даже если это не так, и программа затем блокируется в EndExecuteNonQuery до тех пор, пока не завершится второй SP. Хотя я точно не знаю, я предполагаю, что это связано с тем, что непосредственный процесс SQL завершается (поскольку ему больше нечего делать, вызов EXEC является последней строкой), но подпроцесс продолжает вызов.

Как узнать, полностью ли выполнен SP? Мне кажется, что я не совсем понимаю IAsyncResult.IsCompleted; у меня сложилось впечатление, что он становится true, когда вызов полностью выполнен, но следующее утверждение из этой ссылки заставляет меня думать иначе:

Когда это свойство имеет значение 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);

person Kodithic    schedule 29.03.2015    source источник


Ответы (1)


Если вы используете BeginExecuteNonQuery, ваш код не ожидает выполнения запроса, прежде чем продолжить... Он будет помечен как завершенный асинхронный вызов.

Как вы сказали, одной из альтернатив было бы использование отдельного BackGroundWorker для выполнения хранимой процедуры, если вы хотите, чтобы она выполнялась в фоновом потоке.

См. это

person Saagar Elias Jacky    schedule 29.03.2015
comment
Я думала об этом; Я пытался заставить SP сохранять возвращаемое значение EXEC, а затем SELECT @result, но это ничего не меняет. Будет ли работать статическое значение вместо @result? - person Kodithic; 29.03.2015
comment
@Tukaro проверьте это: stackoverflow.com/questions/14506871/ - person Saagar Elias Jacky; 29.03.2015
comment
Если вы можете сделать вторую хранимую процедуру функцией, вы можете вызвать ее внутри оператора SELECT и сделать последний оператор в вашей хранимой процедуре. - person Saagar Elias Jacky; 29.03.2015
comment
А, понял. Нет, нет никакого реального способа сделать это функцией. Он выполняет множество вычислений/сравнений, а затем сохраняет результаты в таблицу. Потратить время на то, чтобы принудительно включить его в функцию, было бы гораздо, гораздо больше проблем, чем выбрасывать материал C# в другой поток. - person Kodithic; 29.03.2015