none
What's the difference between Task.Factory.StartNew and Task.FromResult

    Question

  • //code snippet var result; Task.FromResult(method(out result)); //run very well var result1; Task.Factory.StartNew(()=>method(out result1));

    // here throw compiler error, result1 is unassigned.


    question: why?

    please help me, thank you.

    Wednesday, April 26, 2017 1:39 AM

Answers

  • Use FromResult when you already have the result and you want to return it. The method immediately returns a task that is already completed and with the given result. There is no calls to the scheduler. This is the fastest, and preferred, way to return a result as a task.

    Task.Factory.StartNew is actually something you should almost never call. Use Task.Run instead if you need to call sync code. This method creates a new task and schedules it using the task scheduler. As such the returned task is likely not completed yet and a thread pool thread (or whatever the scheduler is using) will have to be associated just so you can immediately return a result. It is inefficient when the result is already known.

    But it is very important to note that the 2 code examples you posted initially have completely different behavior. Firstly it wouldn't compile as is. Furthermore your second set of code isn't even waiting on anything. Let's start with the first code.

    FromResult accepts a value to return. You are passing it a method. Therefore the method is executed and then the results of the method call are passed to FromResult which then wraps it in a Task. The key here is the method call you passed as an argument is running sync in the code. So if it takes 1 min to run that code is blocked while the method executes. Only when the method completes does the value get sent to FromResult and the task returned. So if you were returning this task your code is really not async at all.

    With the StartNew (or Run) call, the call returns immediately and the method you provided is run on the task's thread at some point in the future. If that call, again, takes 1 min then the task method still returns immediately but waiting for the result will take 1 min.

    On to the second example you posted. In both cases you aren't actually waiting for the task to complete so your WriteLine method will immediately run. It is completely irrelevant whether the Method call has finished yet or not so what gets printed out is undefined. However in the first call where you're actually executing Method before wrapping it in a task you'll get the correct value because you're actually executing all this code sync. But in the second scenario you'll likely rarely get the correct result as Method will be called after the WriteLine (unless the system isn't busy).

    To better understand what is going on I might recommend that you do the following.

    static void Main ( string[] args )
    {
       Console.WriteLine("Using FromResult");
       var task1 = Task.FromResult(Method());
    Console.WriteLine("Waiting for task"); task1.Wait(); Console.WriteLine("Task completed"); Console.WriteLine("Using Run"); var task2 = Task.Run(() => Method());
    Console.WriteLine("Waiting for task"); task2.Wait(); Console.WriteLine("Task completed"); } static string Method ( ) { Console.WriteLine("Method started"); Thread.Sleep(5000); Console.WriteLine("Method done");
    return "value"; }

    The expected output would be.

    Using FromResult
    Method started
    Method done  (5 seconds later)
    Waiting for task
    Task completed
    
    Using Run
    Waiting for task (may also appear after Method started)
    Method started
    Method done (5 seconds later)
    Task completed

    Michael Taylor
    http://www.michaeltaylorp3.net

    Wednesday, April 26, 2017 1:57 PM
    Moderator

All replies

  • Hi CrayOldPotato,

    Thank you for posting here.

    TaskFactory.StartNew MethodCreates and starts a Task.

    Task.FromResult<TResult> Method (TResult)Creates a Task<TResult> that's completed successfully with the specified result.

    How do you code in method?

    I make a simple example according to your code without compiler error.

      static void Main(string[] args)
            {
                string result1;
                Task.Factory.StartNew(() => method(out result1));
                // here throw compiler error, result1 is unassigned.
            }
            public static void method(out string re)
            {
                re = "hello";
            }

    I hope this would be helpful.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, April 26, 2017 6:49 AM
    Moderator
  • Thank you for answering me

    Wednesday, April 26, 2017 11:34 AM
  • Use FromResult when you already have the result and you want to return it. The method immediately returns a task that is already completed and with the given result. There is no calls to the scheduler. This is the fastest, and preferred, way to return a result as a task.

    Task.Factory.StartNew is actually something you should almost never call. Use Task.Run instead if you need to call sync code. This method creates a new task and schedules it using the task scheduler. As such the returned task is likely not completed yet and a thread pool thread (or whatever the scheduler is using) will have to be associated just so you can immediately return a result. It is inefficient when the result is already known.

    But it is very important to note that the 2 code examples you posted initially have completely different behavior. Firstly it wouldn't compile as is. Furthermore your second set of code isn't even waiting on anything. Let's start with the first code.

    FromResult accepts a value to return. You are passing it a method. Therefore the method is executed and then the results of the method call are passed to FromResult which then wraps it in a Task. The key here is the method call you passed as an argument is running sync in the code. So if it takes 1 min to run that code is blocked while the method executes. Only when the method completes does the value get sent to FromResult and the task returned. So if you were returning this task your code is really not async at all.

    With the StartNew (or Run) call, the call returns immediately and the method you provided is run on the task's thread at some point in the future. If that call, again, takes 1 min then the task method still returns immediately but waiting for the result will take 1 min.

    On to the second example you posted. In both cases you aren't actually waiting for the task to complete so your WriteLine method will immediately run. It is completely irrelevant whether the Method call has finished yet or not so what gets printed out is undefined. However in the first call where you're actually executing Method before wrapping it in a task you'll get the correct value because you're actually executing all this code sync. But in the second scenario you'll likely rarely get the correct result as Method will be called after the WriteLine (unless the system isn't busy).

    To better understand what is going on I might recommend that you do the following.

    static void Main ( string[] args )
    {
       Console.WriteLine("Using FromResult");
       var task1 = Task.FromResult(Method());
    Console.WriteLine("Waiting for task"); task1.Wait(); Console.WriteLine("Task completed"); Console.WriteLine("Using Run"); var task2 = Task.Run(() => Method());
    Console.WriteLine("Waiting for task"); task2.Wait(); Console.WriteLine("Task completed"); } static string Method ( ) { Console.WriteLine("Method started"); Thread.Sleep(5000); Console.WriteLine("Method done");
    return "value"; }

    The expected output would be.

    Using FromResult
    Method started
    Method done  (5 seconds later)
    Waiting for task
    Task completed
    
    Using Run
    Waiting for task (may also appear after Method started)
    Method started
    Method done (5 seconds later)
    Task completed

    Michael Taylor
    http://www.michaeltaylorp3.net

    Wednesday, April 26, 2017 1:57 PM
    Moderator
  • Thank you for answering me so perfectly!!!!

    Task.Factory.StartNew() I use it is coincidential,

     because I must code my code on .net framework 4.0 and I can't find a method could replace Task.Run.

    even I reference Microsoft.Bcl.Async and Poly, perhaps, I don't familiar with those two packages.

    Thursday, April 27, 2017 1:23 AM
  • Task.Run was added in .NET 4.5 so if you aren't running the newer version then you will have to stick with StartNew until you upgrade.
    Thursday, April 27, 2017 2:43 AM
    Moderator