我尝试为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或任何阻止阻塞主线程的东西?
答案 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);
它调用Windows运行时方法RetrieveFeedAsync
,并将.NET Framework扩展方法AsTask
应用于返回的IAsyncOperation
实例。 AsTask
将实例表示为任务,以便您可以等待它。