异步/等待只有多线程?

时间:2014-02-27 12:09:39

标签: c# task-parallel-library async-await

我尝试使用c#的TPL异步执行一个简单的代码。但不是在一个分开的线程!我想只使用主线程,我希望我的WPF应用程序不会冻结。

这样,我不使用方法Task.Run或Task.Factory.StartNew(它们创建一个新线程)。我这样做:

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

但等待之后,它永远不会回来。我究竟做错了什么?谢谢!

2 个答案:

答案 0 :(得分:3)

您已创建Task,但尚未启动它。 await等待任务完成,正如您所见,在这种情况下永远不会。

由于您不想使用后台线程,我会查看@Noseratio的评论。

答案 1 :(得分:1)

WPF等客户端用户界面中async-await的一大好处就是从UI线程中加载非UI工作(如CPU重量级或阻止I / O)。

事实上,这正是你想要的假设的例子。

正确使用async-await后,您的代码可以像这样简洁:

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

或者,如果你没有在任何地方使用CreateList:

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

如果您不需要保留列表:

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

以下是一些您可以阅读的文章,以便快速了解async-await