WPF中的异步任务

时间:2017-03-26 08:14:47

标签: c# .net wpf asynchronous

我尝试为WPF UI Code Behind运行任务。但是当我使用Task.Factory时它没有工作并且注意到了,但是当我使用没有Task.Factory

的代码时它会起作用
public MainWindow()
{
    InitializeComponent();

    GetNews();
}

private void GetNews()
{
    Task.Factory.StartNew(() =>
    {
        FeedReader reader = new FeedReader();
        var news = reader.RetrieveFeed("http://www.bbc.com/feed/");
        foreach (var item in news)
        {
            textBlock.Text = item.Title;
        }
    });
}

如何使用async / await或任何阻止阻塞主线程的东西?

2 个答案:

答案 0 :(得分:8)

因为在尝试修改UI线程之外的UI元素时抛出异常,所以没有任何反应。您应该使用textBlock.Dispatcher.Invoke方法或使FeedReader异步并在您的方法中使用async/await,这是首选。

所以首选的解决方案是(假设RetrieveFeed是异步方法):

private async void GetNews()
{
    FeedReader reader = new FeedReader();
    var news = await reader.RetrieveFeed("http://www.bbc.com/feed/");
    foreach (var item in news)
    {
        textBlock.Text = item.Title;
    }
}

或者,您可以将Feed检索包装在任务中,这将与您当前的实现一起使用:

private async void GetNews()
{
    FeedReader reader = new FeedReader();
    var news = await Task.Run(() => reader.RetrieveFeed("http://www.bbc.com/feed/"));
    foreach (var item in news)
    {
        textBlock.Text = item.Title;
    }
}

这种方法可行,因为await将捕获UI线程的SynchronizationContext,并将值设置为UI线程中的文本框。

这里需要注意的是,async void方法中抛出的异常从未被观察到并且丢失了。因此,您应该将代码包装在GetNews块中的try/catch方法中,并至少记录异常,以便您了解它。

答案 1 :(得分:2)

您可以使用异步版本来检索Feed

SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);
DisplayResults(feed);

检查example from msdn

它调用Windows运行时方法RetrieveFeedAsync,并将.NET Framework扩展方法AsTask应用于返回的IAsyncOperation实例。 AsTask将实例表示为任务,以便您可以等待它。