Reputation: 33
I'm trying to download some twitter info asynchronously and it's blocking the UI thread. I'm using LinqToTwitter (http://linqtotwitter.codeplex.com/) to download the info.
Here's the call to the task
PublicTweetListBox.ItemsSource = await getTweets(twitterCtx);
And here's the task itself
async Task<List<TweetViewModel>> getTweets(TwitterContext twitterCtx)
{
var tweetList = await Task.FromResult<List<TweetViewModel>>(
(from tweet in twitterCtx.Status
where tweet.Type == StatusType.User
&& tweet.ScreenName == UserName.Text
select new TweetViewModel
{
Name = tweet.User.Name,
Tweet = tweet.Text,
ImageUrl = tweet.User.ProfileImageUrl
})
.ToList());
return tweetList;
}
I'm doing something wrong in the way I await downloading the list, TweetViewModel is a custom type if that helps.
Upvotes: 3
Views: 745
Reputation: 7513
Previous answers were good and I just want to add to what has been said. LINQ doesn't support C# 5.0 async, so here's what I did with LINQ to Twitter to support it:
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.SearchMetaData.Query);
srch.Statuses.ForEach(entry =>
Console.WriteLine(
"ID: {0, -15}, Source: {1}\nContent: {2}\n",
entry.ID, entry.Source, entry.Text));
});
}
The MaterializedAsyncCallback takes a parameter of type TwitterAsyncResult<IEnumerable<T>>, resp, where T is the entity type. In this example T is Search. The resp.Status lets you know if an exception was raised during the call and gives you access through the resp.Error property. The resp.State gives you access to the IEnumerable<T>, which is a single Search entity that contains metadata and a list of Status entities (tweets).
The underlying HTTP calls do execute asynchronously, though they use APM, rather than C# 5.0 async. I have plans to look at async closer for both queries and commands in the future, but what LINQ to Twitter uses today is quite effective.
Upvotes: 1
Reputation: 456587
async
and await
do not magically make blocking code non-blocking. Linq-to-twitter is not an asynchronous API, and sticking it in a Task.FromResult
will do nothing.
If you want to push the querying to a background thread, you could use Task.Run
instead of Task.FromResult
. A more efficient (but more involved) solution would be to use an asynchronous twitter API.
Upvotes: 5
Reputation: 34793
It's blocking the UI thread because that is what await
is meant to do. :)
The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.
http://msdn.microsoft.com/en-us/library/hh156528.aspx
IMO this is a "hack" to async programming to work in a synchronous way. To load items in the background and update the ItemSource
when complete, use a worker thread and a call to 'Dispatcher.Invoke' to update the ItemSource
with the results.
Upvotes: -1