何时使用TaskEx.Run与TaskEx.RunEx

poc*_*oco 8 c# wpf task-parallel-library async-await async-ctp

我想知道何时使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以像这样取得同样的结果

  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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 13

使用TaskEx.Run时要在一个线程池上下文中运行同步代码.

使用TaskEx.RunEx时要在一个线程池的环境中运行的异步代码.

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

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

  • TaskEx仅在CTP中.在.Net 4.5中,TaskEx上的方法已集成到Task中. (6认同)
  • 在.Net 4.5 DP中,似乎只有`Task.Run()`,没有'Ex`es. (2认同)

Fir*_*oso 0

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

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

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