-1

I try to execute a simple code asynchronously with TPL of c#. But not in a separated thread! I want to work only with the main thread and I want that my WPF Application doesn't freeze.

That's way, I don't use the methods Task.Run or Task.Factory.StartNew (they create a new thread). I do that:

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var someTask = new Task<List<Person>>(() => CreateList());
        await someTask;
        ListBoxControl.ItemsSource = someTask.Result;
    }

    private List<Person> CreateList()
    {
        var list = new List<Person>();
        list.AddRange(Enumerable.Range(1, 1000000).Select(x => new Person(x)));
        return list;
    }

But after await, it returns never. What am I doing wrong? Thanks!

svick
  • 236,525
  • 50
  • 385
  • 514
MrScf
  • 2,407
  • 5
  • 27
  • 40
  • 2
    1000000 items is the way too many, it will frustrate your user. Anyhow, I answered a similar question here: http://stackoverflow.com/a/21592778/1768303. – noseratio Feb 27 '14 at 13:22
  • Why do you want this to run on the UI thread anyway? Are you trying to solve some other problem? – Panagiotis Kanavos Feb 27 '14 at 16:41
  • yes, that is a simple example. – MrScf Feb 27 '14 at 20:10
  • @Ziggy, also think about what may happen when the user clicks the `ButtonBase` button again, while you're still populating the listbox as a result of the previous click. – noseratio Mar 01 '14 at 01:47

2 Answers2

3

You have created a Task, but you haven't started it. await is waiting for the task to finish, and as you have seen, it never will in this case.

Since you don't want to use a background thread, I'd look into @Noseratio's comment.

Matt Smith
  • 17,026
  • 7
  • 53
  • 103
1

One of the great benefits of async-await in client UIs like WPF is precisely ofloading non UI work (like CPU-heavy taks or blocking I/O) off of the UI thread.

In fact, that's precisely what you want in your hypotetical example.

With the proper use of async-await, your code can be as concise as this:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    ListBoxControl.ItemsSource = await Task.Run((Func<List<Person>>)CreateList);
}

Or, if you are not using CreateList anywhereelse:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    ListBoxControl.ItemsSource = await Task.Run(
        () =>
        {
            var list = new List<Person>();
            list.AddRange(Enumerable.Range(1, 1000000).Select(x => new Person(x)));
            return list;
        }
    );
}

And if you don't need to keep the list:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    ListBoxControl.ItemsSource = await Task.Run(
        () => Enumerable.Range(1, 1000000).Select(x => new Person(x))));
}

Here are a few articles you can read to get up to speed with async-await:

Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59