Monday, June 29, 2009

How To Do Two Things At Once (In C#)

Right this second I'm watching a blogging video by Tim Ferriss and typing this up.   I can't say I'm writing well, or paying much attention to the video - humans tend to do better when focusing on one thing at a time.  Computers on the other hand, can do pretty well doing more than one thing at once, especially when they have more than one processor.  The term for 'doing more than one thing at a time' in code is multithreading, and can be a quite complex to tackle correctly.  But sometimes you just want to do a few things at the same time and come back when they are all complete. .NET helps greatly by providing high level classes that simplify working with multithreading.  In my case, I needed to make a SalesForce webservice call and update a database at the same time.  To do this, I used .NET's Action type:

Action<ContactFormData> beginSendToSalesForce = SendToSalesForce;
var asyncResult = beginSendToSalesForce.BeginInvoke(formData, null, null);
 
using (var context = new ContactFormDataContext())
{
   context.ContactFormDatas.InsertOnSubmit(formData);
   context.SubmitChanges();
}
SetContactFormCookie(formData);
if (this.HasCurrentResourceUrl) LogPageRequest(formData.ContactFormId);
beginSendToSalesForce.EndInvoke(asyncResult);

This works by first creating an Action instance, which you can think of as an object that represents a method call.  Then 'BeginInvoke' is called, kicking off the webservice call, but letting the method continue.  The database is updated, some other stuff done, and then finally we return to the Action instance, calling EndInvoke.  At this point, the app will wait for the webservice call to finish and re-throw any exception that occurs. 

It is important to note that the typical multithreading rules still apply- watch and try to avoid shared state, and if you're doing this in a windows app, don't update any UI elements from the asynchronous method.  But especially for cases where you need to do two only slightly related actions at once, this pattern works well!

No comments: