Skip to content
Tags

,

Executing a LINQ query asynchronously

April 14, 2010

Sometimes I want to execute a costly LINQ query in parallel with other tasks or maybe in parallel with other costly queries. This can be useful, e.g. if you need to load a lot of lookup data not related to eachother.

For that, I’ve made a small extension method:

public static Func<T[]> Async<T>(this IEnumerable<T> enumerable)
{
  System.Diagnostics.Debug.Assert(!(enumerable is ICollection),
  "Async does not work on arrays/lists/collections, only on true enumerables/queryables.");

  // Create delegate to exec async
  Func<IEnumerable<T>, T[]> work = e => e.ToArray();

  // Launch it
  IAsyncResult r = work.BeginInvoke(enumerable, null, null);

  // Return method that will block until completed and rethrow exceptions if any
  return () => work.EndInvoke(r);
}

The usage is then very simple as illustrated by the following code snippet:

// Define some expensive query
IQueryable<string> myExpensiveQuery = context.SystemLog.Where(l => l.Timestamp >= DateTime.Today.AddDays(-10));

// Start async processing
Func<string[]> waitForQueryData = myExpensiveQuery.Async();

// Do a lot of other work, e.g. other queries

// Need my query result now, so block until it's ready and get result
string[] myQueryResults = waitForQueryData();

If the query throws an exception you will get it in the waitForQueryData() call.

About these ads

From → .NET, LINQ, Uncategorized

4 Comments
  1. ivowiblo permalink

    Great!
    NHibernate has something called “Future Queries” that does the same stuff but for hql.

  2. ethan permalink

    Really nice piece of code.

    I’m curious why anyone would try to execute Async against an ICollection — at that point you already have the results of executing the query, right? ;0

    Are you just trying to prevent developer misuse with the Assert? If that’s the case, it might be better to toss an ArgumentException and make it more painfully clear to them.

    • You’re absolutely right! It does not make sense to execute Async() on anything but a true IQueryable or IEnumerable and that is why I made the Assert. I could just as well had thrown an ArgumentException as you suggest.

  3. ivowiblo permalink

    But… an ICollection is an IEnumerable too. I think the behavior will be:
    – if it’s a deferred collection, then it will be initialized asynchronically.
    – if it’s an already loaded collection, then it will return the current values

    so, no matter what do you use, you have the same behavior.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: