I am calling a stored procedure from my application that can take 30 minutes to execute.
I don\'t want to make my user leave the application open for that entire tim
I prefer to use a background service for offline processing, where your user app tells the service what to do and then disconnects. The service can log elapsed times and errors/status, and restart if necessary. WCF is designed for this and supports queues to communicate with.
You can use the BeginExecuteXXX/EndExecuteXXX methods (depending whether it returns a result or not) of the SqlCommand
, passing a callback delegate.
I suggest a re-architecture. Create a "work queue" table where you log requests to run the stored procedure. Then either have a Windows Service or a SQL Server job check that work queue from time to time (or be really ingenious and use a trigger) to kick off the stored procedure. Have the stored procedure update the progress from time to time in the work queue table, and your front-end can look at that an tell the user the progress, and then display the results when they're done.
Another method that you could do would be to allow your application to run in the background (possibly in the notification area) and then exit or notify when the job completes. You could use this by using the BeginExecuteNonQuery and EndExecuteNonQuery methods to allow it to run in a separate thread.
let them shut down the app and come back later
If you're going to allow them to completely close the app, you'll have to start up a seperate .exe or something in a different ThreadPool that executes your code calling the stored procedure. Otherwise your thread will die when you close the app.
Your application's main window does not need to be open. If you launched it as a secondary thread, it will continue to run so long as IsBackground == false
. I usually prefer to do this stuff through SQL Server Agent or as a client-server application (nothing prevents a client-server app from both running on the same machine, or even being the same binary).
It's been a while...
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's 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.
}