9

我试图了解何时使用TaskEx.Run. 我提供了两个我在下面编写的代码示例,它们产生了相同的结果。我没有看到的是为什么我会采用Task.RunEx TaskEx.RunEx方法,我确信这是有充分理由的,并希望有人可以填补我的空缺。

async Task DoWork(CancellationToken cancelToken, IProgress<string> progress)
{
    int i = 0;
    TaskEx.RunEx(async () =>
        {
            while (!cancelToken.IsCancellationRequested)
            {
                progress.Report(i++.ToString());
                await TaskEx.Delay(1, cancelToken);
            }
        }, cancelToken);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
    if (button.Content.ToString() == "Start")
    {
        button.Content = "Stop";
        cts.Dispose();
        cts = new CancellationTokenSource();
        listBox.Items.Clear();
        IProgress<string> progress = new Progress<string>(s => 
        {
            listBox.Items.Add(s); 
            listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
        });
        DoWork(cts.Token, progress);
    }
    else
    {
        button.Content = "Start";
        cts.Cancel();
    }
}

我可以达到同样的结果

  async Task DoWork(CancellationToken cancelToken)
    {
        int i = 0;
        while (!cancelToken.IsCancellationRequested)
        {
            listBox.Items.Add(i++);
            listBox.ScrollIntoView(listBox.Items[listBox.Items.Count - 1]);
            await TaskEx.Delay(100, cancelToken);

        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (button.Content.ToString() == "Start")
        {
            button.Content = "Stop";
            cts.Dispose();
            cts = new CancellationTokenSource();
            listBox.Items.Clear();
            DoWork(cts.Token);
        }
        else
        {
            button.Content = "Start";
            cts.Cancel();
        }
    }
4

3 回答 3

13

TaskEx.Run当您想在线程池上下文中运行同步代码时使用。

TaskEx.RunEx当您想在线程池上下文中运行异步代码时使用。

Stephen Toub 有两篇与行为差异相关的博文:

这只是创建任务的几个选项之一。如果您不必使用Run/ RunEx,那么您不应该使用。使用简单的async方法,只有在需要在后台运行某些东西时才使用Run/ 。RunEx

于 2012-02-17T20:27:49.930 回答
1

您的两种方法之间的区别在于DoWork()第一种(使用TaskEx.RunEx())根本不是异步的。它完全同步执行,在另一个线程上启动另一个任务,并立即返回一个 completed Task。如果您await编辑或Wait()编辑该任务,它不会等到内部任务完成。

于 2012-02-17T22:50:59.340 回答
0

据我了解,Task.Run 在大多数情况下都会产生一个新线程。

重要的是要注意,仅仅因为您将方法标记为异步并使用等待程序,这并不(必然)意味着正在创建新线程,在许多情况下将完成安排在相同的执行线程上。

这里的技巧与 SchedulingContext 有关。如果它是为多线程单元设置的,那么您将把完成委托给线程池上的可行线程。如果您像所有 WPF 和 WinForms UI 代码一样处于单线程单元中,那么它将返回调用线程以完成,从而允许直接在 UI 上完成工作,而无需在代码中进行可见的线程编组。

于 2012-02-17T20:22:51.303 回答