Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between Task.Run and Task.Factory.StartNew

I know this question has been asked before, but I didn't get the right answer after googling SO.

I have these lines of code:

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

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

After a successful run of DoSomething, Task.Run throws TaskCanceledException while Task.Factory.StartNew works fine. Why?

further reading: Stephen Clearly on why not use Task.Factory.StartNew
MSDN Link

UPDATE 2: Sample Code:

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;
}
like image 681
Milad Avatar asked Nov 15 '16 11:11

Milad


1 Answers

Task.Run is actually implemented in terms of the same logic used for Task.Factory.StartNew, just passing in some default parameters. When you pass an Action to Task.Run:

Task.Run(someAction);

that’s exactly equivalent to:

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

Read more here.

If you pass CancellationToken.None, TaskCreationOptions.DenyChildAttach and TaskScheduler.Default arguments for Task.Factory.StartNew parameters you should see the same result.

like image 143
CharithJ Avatar answered Oct 05 '22 11:10

CharithJ