Выполнить асинхронную хранимую процедуру из формы окна и затем отключить?
Я вызываю хранимую процедуру из своего приложения, которое может занять 30 минут.
Я не хочу, чтобы мой пользователь оставил приложение открытым в течение всего этого периода времени. Поэтому я хотел бы назвать sproc, позволить ему летать и позволить им закрыть приложение и вернуться позже.
Как я могу это сделать?
Ответы
Ответ 1
Это на самом деле довольно распространенный сценарий. Вы не можете сделать что-то клиентское, потому что клиент может уйти и отключиться, и вы потеряете работу, достигнутую до сих пор. Решение состоит в том, чтобы использовать Активация Service Broker: вы создаете службу в базе данных и присоединяете активированную процедуру. В своем приложении (или странице ASP) вы отправляете сообщение службе и вставляете необходимые параметры для своей процедуры. После того, как ваша заявка будет совершена, сообщение активирует процедуру обслуживания. процедура обслуживания считывает параметры из сообщения и вызывает вашу процедуру. поскольку активация происходит на потоке сервера, не связанного с вашим исходным соединением, это является надежным. Фактически, сервер может даже выключиться и перезагрузиться во время выполнения вашей процедуры, и работа будет отменена, а затем возобновлена, так как активирующее сообщение снова запустит процедуру обслуживания после перезапуска.
Обновление
Я опубликовал информацию о том, как это сделать, включая пример кода в моем блоге: Выполнение асинхронной процедуры.
Ответ 2
Вы можете использовать методы BeginExecuteXXX
/EndExecuteXXX
(в зависимости от того, возвращает ли он результат или нет) SqlCommand
, передавая делегат обратного вызова.
Ответ 3
Я предлагаю повторную архитектуру. Создайте таблицу "рабочая очередь", в которой вы регистрируете запросы для запуска хранимой процедуры. Затем либо выполните проверку службы Windows, либо задание SQL Server, чтобы время от времени работать (или быть очень изобретательным и использовать триггер), чтобы запустить хранимую процедуру. Периодически обновляйте хранимую процедуру в рабочей таблице задач, и ваш внешний интерфейс может посмотреть на это, сообщить пользователю о прогрессе и затем отобразить результаты, когда они будут сделаны.
Ответ 4
Если вы действительно хотите полностью закрыть приложение, я предлагаю вам определить задание в агенте SQL Server и просто выполнить инструкцию T-SQL, чтобы запустить это задание вручную. Синтаксис:
sp_start_job
{ [@job_name =] 'job_name'
| [@job_id =] job_id }
[ , [@error_flag =] error_flag]
[ , [@server_name =] 'server_name']
[ , [@step_name =] 'step_name']
[ , [@output_flag =] output_flag]
Задание будет выполнять хранимую процедуру. Вы должны быть немного креативными, чтобы передавать любые аргументы. Например, вставьте параметры в таблицу "queue" и обработайте все строки в очереди.
Вместо задания триггер вставки в вашей очереди также должен работать.
Ответ 5
Я предпочитаю использовать фоновый сервис для автономной обработки, где ваше пользовательское приложение сообщает службе, что делать, а затем отключается. Служба может регистрировать прошедшее время и ошибки/статус и при необходимости перезапускать. WCF предназначен для этого и поддерживает очереди для связи.
Ответ 6
пусть они закрывают приложение и приходят назад позже
Если вы разрешите им полностью закрыть приложение, вам придется запускать отдельный файл .exe или что-то в другом ThreadPool, который выполняет ваш код, вызывающий хранимую процедуру. В противном случае ваш поток будет умирать при закрытии приложения.
Ответ 7
Другим способом, который вы могли бы сделать, было бы позволить вашему приложению работать в фоновом режиме (возможно, в области уведомлений), а затем выходить или уведомлять, когда задание завершается. Вы можете использовать это с помощью методов BeginExecuteNonQuery и EndExecuteNonQuery, чтобы он мог запускаться в отдельном потоке.
Ответ 8
Главное окно вашего приложения не должно быть открытым. Если вы запустили его как дополнительный поток, он будет продолжать работать до тех пор, пока IsBackground == false
. Обычно я предпочитаю делать это через агента SQL Server или в качестве клиент-серверного приложения (ничто не препятствует тому, чтобы приложение клиент-сервер работало на одной машине или даже являлось одним и тем же двоичным кодом).
Прошло некоторое время...
using System.Threading;
.....
Thread _t = null;
void StartProcedure()
{
_t = new Thread(new ThreadStart(this.StartProc));
_t.IsBackground = false;//If I remember correctly, this is the default value.
_t.Start();
}
bool ProcedureIsRunning
{
get { return _t.IsRunning; } //Maybe it IsActive. Can't remember.
}
void StartProc(object param)
{
//your logic here.. could also do this as an anonymous method. Broke it out to keep it simple.
}