This project is read-only.

Asyncronous queries

Jun 16, 2009 at 5:31 PM

I've used LINQExtender to create a provider for a REST web service (it's sort of similar to ADO.Net Data Services). The syncronous version works fine technically, but to promote a good user experience I'd like to extend it to support asyncronous calls to the service.

The syncronous provider I have at the moment supports code like

MyRESTContext service = new MyRestContext( baseUri );

IQueryable<Customer> customerNames = service.Customers.Select(c => c.Name);

foreach (string name in customerNames)

{ Console.WriteLine(name); }

Taking the ADO.Net Data Services client library as an example, I'd like to do something like

MyRESTContext service = new MyRestContext( baseUri );

IQueryable<Customer> customers = service.Customers

service.Customers.BeginExecute(

   delegate(IAsyncResult results)

   {

      foreach ( string name in customers.EndExecute(results).Select(customer => customer.Name)

      {   Console.WriteLine(name); }

   }

);

Is this possible with LINQExtender? I can't seem to figure out how to do it...

Thoughts, advice or comments welcome!

Jun 17, 2009 at 8:27 PM
Cool idea though.  Actually the idea could be quite differnet.  Like when you are wrtting a LINQ query like
MyRESTContext service = new MyRestContext( baseUri , true); // where true is the async true.

service.Customers.Select(c => c.Name);
// it will raise an event when Query<T>.SelectItem is completed.
OnSelectCompleted()
{
	// your code.
}
What you say ?

Jun 18, 2009 at 8:08 PM

Well, I think the event based idea is better than my original suggestion with delegates, but having the query execute when the Select is called is going against the principle of deferred execution. I would rather have an ExecuteAsync method that raises an ExecuteCompleted event. It could also raise ExecutionProgress events for long running queries where that makes sense (it probably wouldn't for my REST web service case). So you would write

MyRESTContext service = new MyRestContext( baseUri , true); // where true is the async true.

var customers = service.Customers.Select(c => c.Name);

customers.ExecuteCompleted += new ExecuteCompletedEventHandler(OnComplete);

customers.ExecuteProgressChanged += new ExecuteProgressChangedEventHandler(OnUpdate);

...

OnUpdate()

{

//update progress bar or something

}

OnComplete()

{

 //process customers results

};

In my current application I worked around this by making the REST webservice request asyncrounously and temporarily blocking the calling thread using WaitOne(). I then unblobk the thread in the response event handler using AutoResetEvent.Set(). So I effectively make the call syncronous. A bit of a hack, but all I could do at the moment.

You might be interested to know that this is all happening in a Silverlight application, by the way. I compiled the LINQExtender classes as a Silverlight class library and it worked with only a few minor modifications, mostly to do with how string manipulation methods handle cultures. Overall though, it worked with very little effort :o)