locked
What is difference between Async and Task RRS feed

  • Question

  • see this code example

    public Task<List<string>> GetCitiesAsync()
    {
    	GetCities.GlobalWeather list = new GetCities.GlobalWeather();
    	string Data = list.GetCitiesByCountry("India");
    	XmlDocument xmlDoc = newXmlDocument();
    	xmlDoc.LoadXml(Data);
    	XmlNodeList nodes = xmlDoc.DocumentElement.SelectNodes("//Table");
    	List<string> Listcity = new List<string>();
    
    	foreach (XmlNode node in nodes)
    	{
    	Listcity.Add(node["City"].InnerText);
    	}
    	return Task.FromResult(Listcity);
    }
    
    public async Task<ActionResult> GetCitiesByCountryAsync() // Asynchronous Action Method
    {
    	List<string> listofcities = await GetCitiesAsync();
    	return View(listofcities);
    }


    1) first function return Async and second one return Async Task<ActionResult>

    so i like to understand the difference between Async and Task. i know Task class spawn new thread but Async does not.

    2) see first example code which has no async keyword but when it is calling then await is used. when function is not async then how could i use await to call that function ?

    please discuss elaborately to understand difference between Async and Task.

    3) how to read return string value when function type is async and return string?

    var task = _ModelManager.GetModelData(selectDate);
    await Task.WhenAll(task);
    string value= task.Result;

    i am calling my function this way  await Task.WhenAll(task); then i need to read return value by task.Result; ?

    can i read return value without task.Result; ?

    please share knowledge. thanks


    • Edited by Sudip_inn Tuesday, October 13, 2020 12:52 PM
    Tuesday, October 13, 2020 12:52 PM

Answers

  • 1) Both functions return Task, async has nothing to do with this. There is no such type as async. 

    " i know Task class spawn new thread but Async does not."

    That is wrong. Async does absolutely nothing at runtime, it is completely a compile time feature. The only thing that matters is Task. You will find no references to "async" at runtime. This is completely compiler sugar.

    2) Again, async doesn't mean anything at runtime. Both methods return Task and therefore they are called identically at runtime. Async has no impact on the runtime behavior of code. It is just compiler sugar.

    3) Your code is correct although completely redundant. WhenAll is used to wait for ALL tasks you give it to complete. This is effectively a join such that the code blocks until all the async work completes. Once that work is done then you enumerate the tasks to get the results from each using `Result`.

    In your specific example there is no benefit in using WhenAll because you have a single task. Just await the single task.

    string value = await _ModelManager.GetModelData(selectDate);
    

    Let's address your confusion with async and Task. Task is how you run code async. That's it. Nothing else impacts the runtime part of this. If you need to run something async you use Task. If a method returns Task then it can be run async. This is built into the framework and works the same for any .NET language. Imagine a typical async block of code using Task.

    Task<string> SomeMethodAsync ()
    {
       //Do some work
       var task = Task.Run(DoLongWork);
                      
       //Want to do some more work when that is done
       task = task.ContinueWith(DoMoreWork);
    
       //Let's do even more work
       task = task.ContinueWith(DoYetMoreWork);
    
       //Return the task so the caller can wait for it all to get done
       return task;
    }
    
    //Caller
    var task = SomeMethodAsync();
    
    //Wait for it to complete and get the result
    string value = task.Result;
    

    This is how we wrote async code when Task was first introduced. The problem with this code is it is hard to understand with the ContinueWith calls. It gets harder if we need to ensure a method within here is run on the original thread (say a UI update) or if we want to do something if the task fails. But this is ultimately how it works. If you look at the runtime code generated from C# you'll see basically this wrapped in compiler-generated stuff.

    To make it easier to work with C# added support for the keywords async/await. These are only for C# and have no impact on the runtime code. This is compiler sugar just like `var`, auto properties and most other language features that make it easier to write code. Behind the scenes the `async/await` keywords tell the compiler to rewrite your code to the equivalent of what was posted earlier. In this case you can use these helper keywords to dramatically simplify your code and make it easier to read.

    //Task<string> SomeMethodAsync ()
    async Task<string> SomeMethodAsync ()
    {
       //NOTE: Using Task.Run here to run a sync method
       //In real code should be calling async methods
       //so Task.Run is not needed
       //Do some work
       //var task = Task.Run(DoLongWork);
       await Task.Run(DoLongWork);
                      
       //Want to do some more work when that is done
       //task = task.ContinueWith(DoMoreWork);
       await Task.Run(DoMoreWork);
    
       //Let's do even more work
       //task = task.ContinueWith(DoYetMoreWork);
       string result = await Task.Run(DoYetMoreWork);
    
       //Return the task so the caller can wait for it all to get done
       //return task;
       return result;
    }
    
    //Caller
    async Task CallWork ()
    {
       //var task = SomeMethodAsync();
       
       //Wait for it to complete and get the result
       //string value = task.Result;
       string value = await SomeMethodAsync();
    }

    The reason you put `async` on the method is to tell the compiler you want it to rewrite your code. It is basically equivalent to the `override` keyword on a virtual method. The keyword is there to ensure that you and the compiler agree on what is about to happen. The compiler doesn't technically need it but it avoids unexpected behavior so the keyword is required by the language.

    So, in summary, Task is the runtime object you use and all async code will be Task based. Async/await are strictly helper keywords to allow you to write async methods more cleanly. The compiler rewrites your code to use Tasks at compilation. At runtime (other than all the compiler-generated code stuff) there is no distinction between pure Task and async/await code. The runtime neither knows or cares about C#'s async keywords. 


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Sudip_inn Wednesday, October 14, 2020 8:31 PM
    Tuesday, October 13, 2020 5:16 PM

All replies

  • Hello,

    Have you read the docs on Async keyword?

    I am asking because of this statement

    1) first function return Async and second one return Async Task<ActionResult>

    You don't return Async but instead a Task<T>, Task<List<T>> etc


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, October 13, 2020 4:59 PM
  • 1) Both functions return Task, async has nothing to do with this. There is no such type as async. 

    " i know Task class spawn new thread but Async does not."

    That is wrong. Async does absolutely nothing at runtime, it is completely a compile time feature. The only thing that matters is Task. You will find no references to "async" at runtime. This is completely compiler sugar.

    2) Again, async doesn't mean anything at runtime. Both methods return Task and therefore they are called identically at runtime. Async has no impact on the runtime behavior of code. It is just compiler sugar.

    3) Your code is correct although completely redundant. WhenAll is used to wait for ALL tasks you give it to complete. This is effectively a join such that the code blocks until all the async work completes. Once that work is done then you enumerate the tasks to get the results from each using `Result`.

    In your specific example there is no benefit in using WhenAll because you have a single task. Just await the single task.

    string value = await _ModelManager.GetModelData(selectDate);
    

    Let's address your confusion with async and Task. Task is how you run code async. That's it. Nothing else impacts the runtime part of this. If you need to run something async you use Task. If a method returns Task then it can be run async. This is built into the framework and works the same for any .NET language. Imagine a typical async block of code using Task.

    Task<string> SomeMethodAsync ()
    {
       //Do some work
       var task = Task.Run(DoLongWork);
                      
       //Want to do some more work when that is done
       task = task.ContinueWith(DoMoreWork);
    
       //Let's do even more work
       task = task.ContinueWith(DoYetMoreWork);
    
       //Return the task so the caller can wait for it all to get done
       return task;
    }
    
    //Caller
    var task = SomeMethodAsync();
    
    //Wait for it to complete and get the result
    string value = task.Result;
    

    This is how we wrote async code when Task was first introduced. The problem with this code is it is hard to understand with the ContinueWith calls. It gets harder if we need to ensure a method within here is run on the original thread (say a UI update) or if we want to do something if the task fails. But this is ultimately how it works. If you look at the runtime code generated from C# you'll see basically this wrapped in compiler-generated stuff.

    To make it easier to work with C# added support for the keywords async/await. These are only for C# and have no impact on the runtime code. This is compiler sugar just like `var`, auto properties and most other language features that make it easier to write code. Behind the scenes the `async/await` keywords tell the compiler to rewrite your code to the equivalent of what was posted earlier. In this case you can use these helper keywords to dramatically simplify your code and make it easier to read.

    //Task<string> SomeMethodAsync ()
    async Task<string> SomeMethodAsync ()
    {
       //NOTE: Using Task.Run here to run a sync method
       //In real code should be calling async methods
       //so Task.Run is not needed
       //Do some work
       //var task = Task.Run(DoLongWork);
       await Task.Run(DoLongWork);
                      
       //Want to do some more work when that is done
       //task = task.ContinueWith(DoMoreWork);
       await Task.Run(DoMoreWork);
    
       //Let's do even more work
       //task = task.ContinueWith(DoYetMoreWork);
       string result = await Task.Run(DoYetMoreWork);
    
       //Return the task so the caller can wait for it all to get done
       //return task;
       return result;
    }
    
    //Caller
    async Task CallWork ()
    {
       //var task = SomeMethodAsync();
       
       //Wait for it to complete and get the result
       //string value = task.Result;
       string value = await SomeMethodAsync();
    }

    The reason you put `async` on the method is to tell the compiler you want it to rewrite your code. It is basically equivalent to the `override` keyword on a virtual method. The keyword is there to ensure that you and the compiler agree on what is about to happen. The compiler doesn't technically need it but it avoids unexpected behavior so the keyword is required by the language.

    So, in summary, Task is the runtime object you use and all async code will be Task based. Async/await are strictly helper keywords to allow you to write async methods more cleanly. The compiler rewrites your code to use Tasks at compilation. At runtime (other than all the compiler-generated code stuff) there is no distinction between pure Task and async/await code. The runtime neither knows or cares about C#'s async keywords. 


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Sudip_inn Wednesday, October 14, 2020 8:31 PM
    Tuesday, October 13, 2020 5:16 PM
  • Thanks for reply Madam.

    this is not clear why you said this You don't return Async but instead a Task<T>, Task<List<T>> etc

    why i need to design a function which always return Asyn Task<T> ? my function can be like Async string etc

    please discuss the reason. thanks

    Wednesday, October 14, 2020 8:17 PM
  • Sir this is your first code sample

    Task<string> SomeMethodAsync ()
    {
       //Do some work
       var task = Task.Run(DoLongWork);
                      
       //Want to do some more work when that is done
       task = task.ContinueWith(DoMoreWork);
    
       //Let's do even more work
       task = task.ContinueWith(DoYetMoreWork);
    
       //Return the task so the caller can wait for it all to get done
       return task;
    }
    
    //Caller
    var task = SomeMethodAsync();
    
    //Wait for it to complete and get the result
    string value = task.Result;

    How this line will return result string value = task.Result; suppose when i am expecting result then SomeMethodAsync not completed then what result will be stored in string variable value ?

    does the above code at all run or give error when run ?

    suppose i have a function where Task not used only function is Async type. so tell e Async/Await function ever spawn new thread or it always run on main thread ?

    thanks


    • Edited by Sudip_inn Wednesday, October 14, 2020 8:26 PM
    Wednesday, October 14, 2020 8:25 PM
  • "How this line will return result string value = task.Result; suppose when i am expecting result "

    It won't. It returns a Task that has the result inside it. Notice in the Caller section I assign the return value to a Task variable. Then later I use that variable to get the Result. Ultimately this is how task-based code works. This is exactly how the runtime sees it.

    "then SomeMethodAsync not completed then what result will be stored in string variable value ?"

    Result (and Wait()) are blocking calls. If you call either and the task is not complete yet then your code blocks waiting for the response. Hence when whatever code executes after that line you are guaranteed the task has completed. If it hadn't you'd still be blocked on the call to Result. In the pure task-based world of the CLR you don't need to do anything special to wait for a task to complete, just try to fetch the result (if it returns one) or use Wait(), if it doesn't. Note it is at either of these calls that you'll get an exception if the async method threw an exception, as you would expect.

    "does the above code at all run or give error when run ?"

    Yes the above code is valid and would run if you had defined `DoLongWork`, `DoMoreWork` and `DoYetMoreWork` to be functions that return Task<string>. I didn't provide those impls as they aren't relevant to the discussion but if they existed the code would compile and run as you expected.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, October 14, 2020 8:32 PM