WPF中的异步任务

Mik*_*ike 2 .net c# 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;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

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

And*_*nov 9

没有任何事情发生,因为当您尝试修改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;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以将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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法将起作用,因为await将捕获SynchronizationContextUI线程并将值设置为UI线程中的文本框.

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

  • 异步void方法不会吞没异常; 他们在方法开头活动的`SynchronizationContext`上引发它们. (2认同)