Writing a Service that is running on IIS.
Basically looks like this:
void ProcessRequest(HttpContext context)
{
<Init Stuff>
<Access DB> // This may potentially stall for DB access
<Write Output to conext stream>
}
By stalling the thread in the <Access DB> section we are basically blocking one of the IIS service threads. So looking around a way to get around this is:
IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
this.del = new AsyncTaskDelegate(ProcessRequest);
this.del.BeginInvoke(context, cb, extraData);
}
void EndProcessRequest(IAsyncResult result)
{
this.del.EndInvoke(ar);
}
This looks like it creates another thread to invoke the ProcessRequest(). Thus we are still stalling on the <Access DB> but this time we are stalling using a thread that does not belong to IIS. To me this is nice and symmetrical and keeps the code clean and easy to read.
Talking to a colleague, he says this does not buy you anything as the thread is still stalled. I agree but counter that it is not an IIS thread so it does buy me something. BUT he claims that if we use BeginProcessRequest() to make sure that the only the <Access DB> is done async then we can buy a lot more as no threads will be stalled.
This is psedu code as I have not worked out the details:
void ProcessRequest(HttpContext context)
{ /* Do Nothing */ }
IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
<Init Stuff>
this.command = <Access DB>.getSQLCommand();
this.command.BeginExecuteNonQuery(cb,extraData); // Assume we want to wait for this to complete.
}
void EndProcessRequest(IAsyncResult result)
{
this.command.EndExecuteNonQuery(result);
<Write Output to conext stream>
}
I can see this being an advantage of this does not stall the thread that executes BeginExecuteNonQuery(). But this requires the underlying implementation to use select() to detect when the DB call actually has data waiting to be read. While the easier way to implement it would be to just stall the thread waiting for a response (in which case adding the extra granularity does not buy me anything).
So does anybody have any references to indicate what the better method actually is?
Or have notes on how the underlying implementation of BeginExecuteNonQuery() works?
Or just any general information that may help.
Thanks
Edit:
The SqlConnection class contains a thread pool.
Thus when you do BeginExecuteNonQuery() on a SqlCommand it actually does not need to create a thread. The request is sent and the main control thread will spin up a thread from the pool when data is returned from the SQL-Server. Thus option 3 above does not neadlesly waste threads or cause a thread to hang when doing the DB operation async.