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

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

Если определенный параметр имеет значение true, вызываемая хранимая процедура будет EXEC другой хранимой процедурой в самом конце. Похоже, что когда этот вторичный вызов происходит, 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);

1 ответ

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

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

Отослать это

Другие вопросы по тегам