等待的任务未异步运行

3
我将尝试异步下载一些Twitter信息,但它会阻塞UI线程。我正在使用LinqToTwitter(http://linqtotwitter.codeplex.com/)来下载信息。
以下是任务的调用:
PublicTweetListBox.ItemsSource = await getTweets(twitterCtx);

以下是具体任务内容:

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;

}

我在等待下载列表的方式上出现了问题,如果这有助于解决问题,TweetViewModel是一种自定义类型。
3个回答

5

asyncawait不能神奇地将阻塞代码变为非阻塞。Linq-to-twitter不是一个异步API,将其放入Task.FromResult中将无法发挥作用。

如果您想将查询推送到后台线程,可以使用Task.Run而不是Task.FromResult。更高效(但更复杂)的解决方案是使用异步Twitter API。


谢谢,我会研究一下Task.Run,也许会使用不同的API。 - Nick Ward

1
之前的回答都很好,我只是想补充一下。LINQ不支持C# 5.0异步操作,所以这里是我在使用LINQ to Twitter时所做的支持:
    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));
        });
    }

MaterializedAsyncCallback接受一个类型为TwitterAsyncResult<IEnumerable<T>>的参数resp,其中T是实体类型。在此示例中,T是Search。 resp.Status让您知道是否在调用期间引发了异常,并通过resp.Error属性让您访问它。 resp.State让您访问IEnumerable<T>,它是包含元数据和状态实体(推文)列表的单个搜索实体。
底层HTTP调用确实以异步方式执行,但它们使用APM而不是C# 5.0 async。我计划将来更仔细地查看异步查询和命令,但是LINQ to Twitter今天使用的方法非常有效。 @JoeMayo

非常感谢Joe!我目前非常喜欢linqtotwitter,期待异步支持,继续保持好工作。 - Nick Ward

-1

它会阻塞UI线程,因为这就是await的作用。 :)

await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。该任务代表正在进行的工作。

http://msdn.microsoft.com/en-us/library/hh156528.aspx

在我看来,这是一种将异步编程以同步方式运行的“hack”方法。要在后台加载项目并在完成后更新ItemSource,请使用工作线程和调用“Dispatcher.Invoke”来使用结果更新ItemSource


1
await接收到一个尚未完成的操作时,它会暂停方法的执行,但不会阻塞线程。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接