Friday, March 23, 2012

Don't call it a thread-off

I had to do something incredibly cool the other day so I thought I would share.

A web site I was building calls two WCF services per data request.  It's not my architecture.  But in this case, the data call was to take a text file and dump the contents into the SQL database.  Since those files can get longer than a typical HTTP request can stay alive, I started getting timeout errors while waiting for the WCF service to finish its processing.  My first thought was to make the processing asynchronous.

The fun thing about multithreading and asynchronous operations is that I was passing the file name and path to the saved text file into the WCF service.  I needed to spin off a new thread while passing in the parameter, which I didn't expect to be this easy.  Here's the code:

Public Function ImportThis (byval psFileName as string) as Boolean
     Dim MyAsync as New System.Threading.Thread(AddressOf AsyncImport)
     Return True
End Function

Private Sub AsyncImport(psFileName as String)
     'Put code to process text file here
End Sub

The end result is that my service returns true back to the calling page, but of course I wrapped it in a try/catch statement and had to do a couple of other things in there.  I watched the database just add records into the table, then clear them back out as the DB finished processing the import.  All while the web site thinks everything is ok.  Good practices also dictated that I put plenty of error trapping in the AsyncImport process, where it emails an administrator a list of bad records in the import, or anything else that goes wrong. 

Bottom line is that it was easy to spin off a new thread for some asynchronous processing, and pass a parameter value into the process.  Method #2 for doing the same thing is to create a private property for the service, set the property value in the public function, and call the property value from the async function.  But just passing the argument in is still the simpler approach.