Task.Run和Task.Factory.StartNew有什么区别

Mil*_*lad 5 c# multithreading task task-parallel-library c#-4.0

我知道之前已经问过这个问题,但谷歌搜索后我得不到正确的答案.

我有这些代码行:

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

Task.Factory.StartNew(() => DoSomething())
    .ContinueWith(t=>Log.Error(t,"Error"),TaskContinuationOptions.OnlyOnFaulted);
Run Code Online (Sandbox Code Playgroud)

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

进一步阅读: Stephen Clearly为什么不使用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;
}
Run Code Online (Sandbox Code Playgroud)

Cha*_*thJ 5

Task.Run实际上是根据用于Task.Factory.StartNew的相同逻辑实现的,只是传入一些默认参数.将Action传递给Task.Run时:

Task.Run(someAction);
Run Code Online (Sandbox Code Playgroud)

这完全等同于:

Task.Factory.StartNew(someAction, 
    CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多.

如果您传递CancellationToken.None,TaskCreationOptions.DenyChildAttachTaskScheduler.Default为自变量Task.Factory.StartNew参数,你会看到同样的结果.

  • 你不会看到完全相同的行为,有一个重要的差异.`Task.Run(`有重载,它接受`Func <Task>`或`Func <Task <T >>`作为参数.这允许你将异步函数传入`Task.Run(`如果你尝试使用`StartNew(`必须在返回的任务上调用`.Unwrap()`来执行异步函数以获得相同的行为. (3认同)
  • @Sepinood:可能是这个http://stackoverflow.com/questions/26577519/why-is-taskcanceledexception-thrown-and-does-not-always-breaks-into-the-debugger或http://stackoverflow.com/问题/ 27196451 /时,做任务,runaction-的CancellationToken - 投掷taskcanceledexception (2认同)