Mike
Mike

Reputation: 181

Async Task in WPF

I tried to run a task for a WPF UI Code Behind . but it doesn't work and noting happend when I use Task.Factory but it works when I use the code without 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;
        }
    });
}

How can I use async/await or anything that prevent block main thread?

Upvotes: 4

Views: 8616

Answers (2)

user6996876
user6996876

Reputation:

You can use the async version to retrieve the feed

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

Check the example from msdn.

It calls the Windows Runtime method, RetrieveFeedAsync, and applies a .NET Framework extension method, AsTask, to the returned IAsyncOperation instance. AsTask represents the instance as a Task, so that you can await it.

Upvotes: 2

Andrii Litvinov
Andrii Litvinov

Reputation: 13192

Nothing happens because an exception is thrown as you are trying to modify UI element outside of UI thread. You should either use textBlock.Dispatcher.Invoke method or make FeedReader asynchronous and use async/await in your method, which is preferable.

So the prefered solution would be (provided RetrieveFeed is async method):

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;
    }
}

Alternatively you could wrap feed retrieval in a task, which will work with your current implementation:

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;
    }
}

This approach will work because await will capture SynchronizationContext of UI thread and will set value to the textbox in UI thread.

And the caveat here is that exceptions thrown in async void method are never observed and are lost. So you should wrap the code inside GetNews method in try/catch block and at least log the exception so you are aware of it.

Upvotes: 11

Related Questions