Doing an asynchronous search in Windows 8

I was teaching a class today at HP, and demonstrating how to implement Search suggestions for in app search. The pattern is easy: you hook an event, and in the event, return any matches. Here is an example:

  var sp = SearchPane.GetForCurrentView();
  sp.SuggestionsRequested += OnSearchPaneSuggestionsRequested;

// ... 



void OnSearchPaneSuggestionsRequested(object sender, SearchPaneSuggestionsRequestedEventArgs args) { args.Request.SearchSuggestionCollection.AppendQuerySuggestions( (from t in App.ViewModel.ConferenceInfos where t.Name.StartsWith(args.QueryText, StringComparison.CurrentCultureIgnoreCase) select t.Name).Take(5)); }

Well, the student asked, what if you need to do a search that requires a web service call, or some other asynchronous call? Can that be done? And what if the call takes a while, and the user keeps typing while the first search is in progress? Good questions indeed!

 

So, I modified my method as follows: 

 private static int callcount = 0;

        public async void OnSearchPaneSuggestionsRequested(object sender, SearchPaneSuggestionsRequestedEventArgs args)
        {
            callcount++;
            System.Diagnostics.Debug.WriteLine(String.Format("Call {0} at {1} for {2}", callcount, DateTime.Now, args.QueryText));
            var deferral = args.Request.GetDeferral();
            try
            {
                await Task.Delay(10000);
                args.Request.SearchSuggestionCollection.AppendQuerySuggestions(
                    (from t in App.ViewModel.ConferenceInfos
                     where t.Name.StartsWith(args.QueryText, StringComparison.CurrentCultureIgnoreCase)
                     select t.Name).Take(5));
            }
            finally
            {
                deferral.Complete();
                System.Diagnostics.Debug.WriteLine(String.Format("Call {0} at {1} for {2} returning", callcount, DateTime.Now, args.QueryText));
            }
        }

First of all, the assignment sp.SuggestionsRequested += …. did not need to change, evidently there is no issue assigning an asynchronous method to an event.

Second, without the calls to GetDeferral and deferral,Complete, the code blew up with an exception, on the line that assigns the results to the SearchSuggestionCollection (the method was called at an unexpected time!). That didn’t surprise me. In most cases where you need to be able to do something async in a callback, you will be provided with some parameter that you can call GetDeferral on.

 

When I ran this code, I typed the letter u n i v with a 1 second spacing. I noted that I didn’t get any search results back until 10 seconds after I stopped typing. So, no intermediate results for each of the letters with 1 second delay, it looks like the caller discards the results if more typing has happened since the call started.

 

Here is the output in the Output window:

 

Call 1 at 10/10/2012 3:27:29 PM for u
Call 2 at 10/10/2012 3:27:30 PM for un
Call 3 at 10/10/2012 3:27:31 PM for uni
Call 4 at 10/10/2012 3:27:33 PM for univ
Call 4 at 10/10/2012 3:27:39 PM for u returning
The thread '<No Name>' (0x2b24) has exited with code 0 (0x0).
Call 4 at 10/10/2012 3:27:40 PM for un returning
The thread '<No Name>' (0x3a24) has exited with code 0 (0x0).
Call 4 at 10/10/2012 3:27:41 PM for uni returning
Call 4 at 10/10/2012 3:27:43 PM for univ returning
The thread '<No Name>' (0x1bd4) has exited with code 0 (0x0).
The thread '<No Name>' (0x3064) has exited with code 0 (0x0).
The thread '<No Name>' (0x3320) has exited with code 0 (0x0).

 

It looks like each call got it’s own thread, and also you can see that they were a) not queued up sequentially, and b) not aborted by the caller, they each ran to completion 10 seconds after they started.

 

Takeaways?

 

1) You can implement asynchronous searches.

2) If they are expensive and you need to abort existing searches when new ones come in, you need to implement that yourself.

 

Hope that helps!

comments powered by Disqus