This project has moved and is read-only. For the latest updates, please go here.

Handling exceptions in asynchronous queries

Aug 11, 2012 at 7:50 AM

Hi Joe,

I was wondering how to handle exceptions when making API calls from Windows Phone. Using the code from your blog post:

(from tweet in ctx.Status
 where tweet.Type == StatusType.Public
 select tweet)
.AsyncCallback(tweets =>
	Dispatcher.BeginInvoke(() =>
		var publicTweets =
			(from tweet in tweets
			 select new PublicTweet
				 UserName = tweet.User.Identifier.ScreenName,
				 Message = tweet.Text,
				 ImageSource = tweet.User.ProfileImageUrl

		PublicTweetListBox.ItemsSource = publicTweets;

Wrapping a try-catch clause around the whole block obviously doesn't work, and wrapping it around the Action delegate inside the AsyncCallback doesn't do anything either.

So, how would you handle exceptions in this case? I know you can check the rate limit beforehand but it takes quite some time to do so and is unnecessary in most cases, plus it's not always the cause of the exception.

Sorry if I'm overlooking something here but I couldn't find much information on the style of asynchronous LINQ queries you're doing here. Thanks in advance!

Aug 17, 2012 at 3:59 AM


Thanks for bringing this up. I've implemented TwitterAsyncResponse<T> for side-effects and streams, but haven't added it to queries yet. It will let you query the status of the response and have access to the exception.  I've opened a new issue here:

This is important enough that I'll probably start on it this weekend.


Aug 20, 2012 at 6:22 AM

I just did a check-in on this. What I did was add a new extension method, MaterializedAsyncCallback.  This helps avoid breaking existing code, but also removes the artificial requirement to call another extension method, like ToList, to materialize the query. Per my original intent in this, exception handling is available.  Here's a console example:

        static void AsyncSearchSample(TwitterContext twitterCtx)
            (from search in twitterCtx.Search
             where search.Type == SearchType.Search &&
                   search.Query == "LINQ To Twitter"
             select search)
            .MaterializedAsyncCallback(resp =>
                if (resp.Status != TwitterErrorStatus.Success)
                    Exception ex = resp.Error;
                    // handle error
                    throw ex;

                Search srch = resp.State.First();
                Console.WriteLine("\nQuery: {0}\n", srch.QueryResult);

                srch.Results.ForEach(entry =>
                        "ID: {0, -15}, Source: {1}\nContent: {2}\n",
                        entry.ID, entry.Source, entry.Text));

The resp parameter for the MaterializedAsyncCallback is a TwitterAsyncResponse<IEnumerable<T>> with various properties for getting at the response info. I have more testing to do and noticed that I have more work to do in side-effect exception handling, but this is checked-in and available if you wanted to download the code and try it out.  You can test error handling in this particular search by sending in a query that has an empty string, which causes Twitter to return a 403 Not Found.


Aug 26, 2012 at 4:26 PM
Edited Aug 26, 2012 at 4:27 PM

Hi Joe,

just downloaded the newest version and, from what I've seen so far, it looks to be fantastic! Exactly what I was looking for, and I no longer have to guess which extension method to call to materialize the query, which wasn't always obvious in the old version (at least to me).

One more question, since Twitter sometimes returns incorrect JSON, which previously resulted in a JsonException, will that still happen or is it included in the new exception handling?

Thanks a lot again for this wonderful library!

Aug 26, 2012 at 8:49 PM

Thanks.  The incomplete JSON is coming from Twitter, so the best strategy is to retry when it happens. In the async scenario, the exception will always appear in the TwitterAsyncResponse<>.


Aug 26, 2012 at 8:50 PM

Okay good it's included in the response, that's all I wanted to know. Thanks!