【问题标题】:What is the difference between Task.Run and Task.Factory.StartNewTask.Run 和 Task.Factory.StartNew 有什么区别
【发布时间】:2016-11-15 11:25:48
【问题描述】:

我知道以前有人问过这个问题,但是在谷歌搜索之后我没有得到正确的答案。

我有这几行代码:

Task.Run(() => DoSomething())
    .ContinueWith(t=>Log.Error(t,"Error"), TaskContinuationOptions.OnlyOnFaulted);

Task.Factory.StartNew(() => DoSomething())
    .ContinueWith(t=>Log.Error(t,"Error"),TaskContinuationOptions.OnlyOnFaulted);

DoSomething 成功运行后,Task.Run 抛出 TaskCanceledExceptionTask.Factory.StartNew 工作正常。为什么?

进一步阅读: Stephen Clearly on why not use Task.Factory.StartNew
MSDN Link

更新 2: 示例代码:

private async void button27_Click(object sender, EventArgs e)
{
    var r = new Random(System.DateTime.Now.Millisecond);

    await Task.Factory.StartNew(
        () => {
            Divide(r.Next(100), r.Next(-1, 10));
            Log.Information("Divide Done!");
        },
        CancellationToken.None,
        TaskCreationOptions.DenyChildAttach,
        TaskScheduler.Default)
    .ContinueWith(
        t => {
            Log.Error(t.Exception,"There is an exception on Divide");
        },
        TaskContinuationOptions.OnlyOnFaulted);
}

private static void Divide(int a, int b)
{
    var c = a/b;
}

【问题讨论】:

  • 不,不是。它没有回答我的问题,这就是为什么会发生抛出异常。它描述了我已经知道的。谢谢。
  • 我已经回滚了你的问题,因为你完全改变了它,使现有的答案无效。如果您有新问题,请发布新问题。
  • @Sepinood - 好的,我撤回了近距离投票。尽管我相信标题 Task.Run 和 Task.Factory.StartNew 有什么区别? 在建议的副本中得到了回答。所有当前的答案或多或少都与建议的重复内容相同,并引用了相同的来源。
  • @smoksnes 感谢您的宝贵时间。我很感激。

标签: c# multithreading c#-4.0 task-parallel-library task


【解决方案1】:

Task.Run 实际上是根据用于 Task.Factory.StartNew,只是传入一些默认参数。什么时候 您将 Action 传递给 Task.Run:

Task.Run(someAction);

这完全等同于:

Task.Factory.StartNew(someAction, 
    CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

阅读更多here

如果您为Task.Factory.StartNew 参数传递CancellationToken.NoneTaskCreationOptions.DenyChildAttachTaskScheduler.Default 参数,您应该会看到相同的结果。

【讨论】:

  • 谢谢,它帮助了我。我完全更新了这个问题。我认为这与TPL的设计有关。
  • 你不会看到完全相同的行为,有一个重要的区别。 Task.Run( 具有以Func<Task>Func<Task<T>> 作为参数的重载。这允许您将异步函数传递给Task.Run(,如果您尝试使用StartNew( 执行异步函数,则必须在返回的任务上调用.Unwrap() 以获得相同的行为。
  • @ScottChamberlain 感谢您提供的一系列精彩细节以确保清晰
猜你喜欢
  • 2016-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2021-08-14
相关资源
最近更新 更多