Application hangs while running async task - c#

I am learning about async/await and created a dummy console application. When I try to get the result from async method the program just hangs. Any idea what is wrong in the following code.
static void Main(string[] args)
{
var task = Task.Factory.StartNew(() => 5);
var x = TestAsync();
//x.Start();
Console.WriteLine(x.Result);
}
private static Task<int> CalculateValue()
{
Console.WriteLine("In CalculateValue"); // This line is printed.
Task<int> t = new Task<int>(GetValue); // The program hangs here.
return t;
}
public static async Task<int> TestAsync()
{
int result = await CalculateValue();
return result;
}
private static int GetValue()
{
return 10;
}

First of all:
Task<int> t = new Task<int>(GetValue); // The program hangs here.
is incorrect, the program actually hangs here :
Console.WriteLine(x.Result);
.Result blocks current thread until task x completes execution and returns result. It never completes as it awaits task returned by CalculateValue method whis is this task:
Task<int> t = new Task<int>(GetValue);
This is so called 'cold Task' which means that it's a task in an inactive state.
To start a 'hot' task (which basically means start the task) use the Task.Run method:
Task<int> t = Task.Run(GetValue);

Related

async Main wouldn't compile [duplicate]

I copied below code from this link.But when I am compiling this code I am getting an entry point cannot be marked with the 'async' modifier. How can I make this code compilable?
class Program
{
static async void Main(string[] args)
{
Task<string> getWebPageTask = GetWebPageAsync("http://msdn.microsoft.com");
Debug.WriteLine("In startButton_Click before await");
string webText = await getWebPageTask;
Debug.WriteLine("Characters received: " + webText.Length.ToString());
}
private static async Task<string> GetWebPageAsync(string url)
{
// Start an async task.
Task<string> getStringTask = (new HttpClient()).GetStringAsync(url);
// Await the task. This is what happens:
// 1. Execution immediately returns to the calling method, returning a
// different task from the task created in the previous statement.
// Execution in this method is suspended.
// 2. When the task created in the previous statement completes, the
// result from the GetStringAsync method is produced by the Await
// statement, and execution continues within this method.
Debug.WriteLine("In GetWebPageAsync before await");
string webText = await getStringTask;
Debug.WriteLine("In GetWebPageAsync after await");
return webText;
}
// Output:
// In GetWebPageAsync before await
// In startButton_Click before await
// In GetWebPageAsync after await
// Characters received: 44306
}
The error message is exactly right: the Main() method cannot be async, because when Main() returns, the application usually ends.
If you want to make a console application that uses async, a simple solution is to create an async version of Main() and synchronously Wait() on that from the real Main():
static void Main()
{
MainAsync().Wait();
}
static async Task MainAsync()
{
// your async code here
}
This is one of the rare cases where mixing await and Wait() is a good idea, you shouldn't usually do that.
Update: Async Main is supported in C# 7.1.
Starting from C# 7.1 there are 4 new signatures for Main method which allow to make it async(Source, Source 2, Source 3):
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
You can mark your Main method with async keyword and use await inside Main:
static async Task Main(string[] args)
{
Task<string> getWebPageTask = GetWebPageAsync("http://msdn.microsoft.com");
Debug.WriteLine("In startButton_Click before await");
string webText = await getWebPageTask;
Debug.WriteLine("Characters received: " + webText.Length.ToString());
}
C# 7.1 is available in Visual Studio 2017 15.3.
I'm using C# 8 and its working fine.
static async Task Main(string[] args)
{
var response = await SomeAsyncFunc();
Console.WriteLine("Async response", response);
}
OR without "await" keyword.
static void Main(string[] args)
{
var response = SomeAsyncFunc().GetAwaiter().GetResult();
Console.WriteLine("Async response", response);
}
The difference between the code in the link's example and yours, is that you're trying to mark the Main() method with an async modifier - this is not allowed, and the error says that exactly - the Main() method is the "entry point" to the application (it's the method that is executed when your application starts), and it's not allowed to be async.
Wrap your async code in MainAsync() - which is an async function
then call MainAsync().GetAwaiter().GetResult();

Running parallel async tasks?

So I've been searching StackOverflow/Google for different methods of running multiple async tasks concurrently. There seemed to be quite the debate between different methods and I just wanted to get some clarification. I'm writing a program to execute a JSON POST request until the server returns a status code of 200. Let's say I want to run 5 of theses tasks in parallel until one returns a status code of 200. Please try not to stray away from the topic, I have no control over the server! Here's my current code,
static bool status = false;
public static async Task getSessionAsync() {
while(!status) { ... }
}
public static async Task doMoreStuff() {
...
}
public static async Task RunAsync()
{
await getSessionAsync ();
await doMoreStuff();
}
public static void Main (string[] args)
{
Task.WhenAll(RunAsync()).GetAwaiter().GetResult();
}
Basically, I'm wondering if it's wrong for me to approach it like this,
public static async Task RunAsync()
{
for(int i = 0; i < 5; i++) {
await getSessionAsync ();
}
await doMoreStuff();
}
This will not run in parallel:
public static async Task RunAsync()
{
for(int i = 0; i < 5; i++) {
await getSessionAsync ();
}
await doMoreStuff();
}
You have to use Task.WhenAny()
public static async Task RunAsync()
{
var tasks = new List<Task>();
for(int i = 0; i < 5; i++) {
tasks.Add(getSessionAsync());
}
await Task.WhenAny(tasks);
await doMoreStuff();
}
If you do not need your current context (i.e. when you are writing a Library and not Frontend code), don't forget to use ConfigureAwait(false) after each await.
Assuming:
private Task<MySession> GetSessionAsync()
{
// ...
}
Option 1
Task.WhenAny
var session = await await Task.WhenAny(Enumerable.Range(0, 5).Select(_ => GetSessionAsync()));
Option 2
You could use the Rx LINQ method called Amb which will observe only the first Observable that returns something.
var session = await Enumerable.Range(0, 5).Select(_ => GetSessionAsync().ToObservable()).Amb().ToTask();

Async/Await behaviour through the stack

I'm curious about how the flow of async works across the stack. When reading about async in C#, you will continually read some version of the following:
If the task we are awaiting has not yet completed then sign up the
rest of this method as the continuation of that task, and then return
to your caller immediately; the task will invoke the continuation when
it completes.
It's the return to your caller immediately part that confuses me. In the below example, assuming something calls MethodOneAsync(), execution hits the await in MethodOneAsync. Does it immediately return to the method that called this? If so, how does MethodTwoAsync ever get executed? Or does it continue down the stack until it detects that it's actually blocked (ie. DoDBWorkAsync()) and then yield the thread?
public static async Task MethodOneAsync()
{
DoSomeWork();
await MethodTwoAsync();
}
public static async Task MethodTwoAsync()
{
DoSomeWork();
await MethodThreeAsync();
}
public static async Task MethodThreeAsync()
{
DoSomeWork();
await DoDBWorkAsync();
}
The part before an await in an async method is executed synchronously. That's the case for all async methods.
Let's assume that instead of await DoDBWorkAsync() we have await Task.Delay(1000).
That means MethodOneAsync starts running, executes DoSomeWork and calls MethodTwoAsync which in turn executes DoSomeWork which calls MethodThreeAsync which again executes DoSomeWork.
Then it calls Task.Delay(1000), gets back an uncompleted Task and awaits it.
That await is logically equivalent to adding a continuation and returning the task back to the caller, which is MethodTwoAsync which does the same and return a Task to the caller and so forth and so forth.
That way when the root delay Task completes all the continuations can run one after the other.
If we make your example a bit more complicated:
public static async Task MethodOneAsync()
{
DoSomeWorkOne();
await MethodTwoAsync();
DoMoreWorkOne();
}
public static async Task MethodTwoAsync()
{
DoSomeWorkTwo();
await MethodThreeAsync();
DoMoreWorkTwo();
}
public static async Task MethodThreeAsync()
{
DoSomeWorkThree();
await Task.Delay(1000);
DoMoreWorkThree();
}
It would be logically similar to doing this with continuations:
public static Task MethodOneAsync()
{
DoSomeWorkOne();
DoSomeWorkTwo();
DoSomeWorkThree();
return Task.Delay(1000).
ContinueWith(_ => DoMoreWorkThree()).
ContinueWith(_ => DoMoreWorkTwo()).
ContinueWith(_ => DoMoreWorkOne());
}
First, let me do a different example so my code further down will make sense
public static async Task MethodOneAsync()
{
DoSomeWork1();
await MethodTwoAsync();
DoOtherWork1();
}
public static async Task MethodTwoAsync()
{
DoSomeWork2();
await MethodThreeAsync();
DoOtherWork2();
}
public static async Task MethodThreeAsync()
{
DoSomeWork3();
await DoDBWorkAsync();
DoOtheWork3();
}
All async await does is turn the above code in to something similar to (but even this is a HUGE simplification) this
public static Task MethodOneAsync()
{
DoSomeWork1();
var syncContext = SynchronizationContext.Current ?? new SynchronizationContext();
var resultTask = MethodTwoAsync();
return resultTask.ContinueWith((task) =>
{
syncContext.Post((state) =>
{
SynchronizationContext.SetSynchronizationContext(syncContext);
DoOtherWork1();
}, null);
});
}
public static Task MethodTwoAsync()
{
DoSomeWork2();
var syncContext = SynchronizationContext.Current ?? new SynchronizationContext();
var resultTask = MethodThreeAsync();
return resultTask.ContinueWith((task) =>
{
syncContext.Post((state) =>
{
SynchronizationContext.SetSynchronizationContext(syncContext);
DoOtherWork2();
}, null);
});
}
public static Task MethodThreeAsync()
{
DoSomeWork3();
var syncContext = SynchronizationContext.Current ?? new SynchronizationContext();
var resultTask = DoDbWorkAsync();
return resultTask.ContinueWith((task) =>
{
syncContext.Post((state) =>
{
SynchronizationContext.SetSynchronizationContext(syncContext);
DoOtherWork3();
}, null);
});
}.
Each await just executes the next layer deeper till it is forced to return a Task, once that happens it starts doing continuations on the tasks when they complete and in that continuation it passes in a delegate representing "the rest of the function" to SynchronizationContext.Post( to get the code scheduled to be executed.
How it is scheduled depends on which SynchronizationContext you are in. In WPF and Winforms it queues it to the message pump, for the default and ASP.NET it queues it on a thread pool worker.
It does return after firing the Task for MethodTwoAsync method (or continues execution, if this Task is immediately done), so the inner Task is executing into SynchronizationContext.Current environment.
And after this Task is done, the .NET state machine return the execution to the point right after the MethodTwoAsync firing, and process the rest of the code.
See more information at MSDN article:

Async/Await - Vicious Circle C# 5.0

The code is below.
I want to call DoLongWork function asynchronously.
But the code ends up synchronous because DoLongWork doesn't await anything.
There is no need for awaiting something in DoLongWork function. Because function itself is long running. Not waiting any resource.
How can I get out of this vicious circle?
class Program
{
static void Main(string[] args)
{
Task<int> task = Foo("Something");
Console.WriteLine("Do it");
Console.WriteLine("Do that");
task.Wait();
Console.WriteLine("Ending All");
}
static async Task<int> Foo(string param)
{
Task<int> lwAsync = DoLongWork(param);
int res = await lwAsync;
return res;
}
static async Task<int> DoLongWork(string param)
{
Console.WriteLine("Long Running Work is starting");
Thread.Sleep(3000); // Simulating long work.
Console.WriteLine("Long Running Work is ending");
return 0;
}
}
You can use Task.Run to execute synchronous work on a background thread:
// naturally synchronous, so don't use "async"
static int DoLongWork(string param)
{
Console.WriteLine("Long Running Work is starting");
Thread.Sleep(3000); // Simulating long work.
Console.WriteLine("Long Running Work is ending");
return 0;
}
static async Task<int> FooAsync(string param)
{
Task<int> lwAsync = Task.Run(() => DoLongWork(param));
int res = await lwAsync;
return res;
}

Understanding async / await in C#

I'm starting to learn about async / await in C# 5.0, and I don't understand it at all. I don't understand how it can be used for parallelism. I've tried the following very basic program:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
This program just blocks on the call to Task.WaitAll() and never finishes, but I am not understanding why. I'm sure I'm just missing something simple or just don't have the right mental model of this, and none of the blogs or MSDN articles that are out there are helping.
I recommend you start out with my intro to async/await and follow-up with the official Microsoft documentation on TAP.
As I mention in my intro blog post, there are several Task members that are holdovers from the TPL and have no use in pure async code. new Task and Task.Start should be replaced with Task.Run (or TaskFactory.StartNew). Similarly, Thread.Sleep should be replaced with Task.Delay.
Finally, I recommend that you do not use Task.WaitAll; your Console app should just Wait on a single Task which uses Task.WhenAll. With all these changes, your code would look like:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
Task task1 = Task1();
Task task2 = Task2();
await Task.WhenAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await Task.Delay(5000);
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(10000);
Debug.WriteLine("Finished Task2");
}
}
Understand C# Task, async and await
C# Task
Task class is an asynchronous task wrapper. Thread.Sleep(1000) can stop a thread running for 1 second. While Task.Delay(1000) won't stop the current work. See code:
public static void Main(string[] args){
TaskTest();
}
private static void TaskTest(){
Task.Delay(5000);
System.Console.WriteLine("task done");
}
When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.
Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.
async and await
Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
Console.ReadLine();
}
private static async void TaskTest(){
await Task.Delay(5000);
System.Console.WriteLine("task done");
}
async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.
Cancel a Task
Since Task is a state machine, there must be a way to cancel the task while task is in running.
static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
var input=Console.ReadLine();
if(input=="stop"){
tokenSource.Cancel();
System.Console.WriteLine("task stopped");
}
Console.ReadLine();
}
private static async void TaskTest(){
try{
await Task.Delay(5000,tokenSource.Token);
}catch(TaskCanceledException e){
//cancel task will throw out a exception, just catch it, do nothing.
}
System.Console.WriteLine("task done");
}
Now, when the program is in running, you can input "stop" to cancel the Delay task.
Your tasks never finish because they never start running.
I would Task.Factory.StartNew to create a task and start it.
public static async Task Task1()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
As a side note, if you're really just trying to pause in a async method, there's no need to block an entire thread, just use Task.Delay
public static async Task Task1()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Debug.WriteLine("Finished Task2");
}
Async and await are markers which mark code positions from where control should resume after a task (thread) completes.
Here's a detail youtube video which explains the concept in a demonstrative manner http://www.youtube.com/watch?v=V2sMXJnDEjM
If you want you can also read this coodeproject article which explains the same in a more visual manner.
http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”and“Await”(Codemarkers)
static void Main(string[] args)
{
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "Main";
Console.WriteLine(Thread.CurrentThread.Name + "1");
TaskTest();
Console.WriteLine(Thread.CurrentThread.Name + "2");
Console.ReadLine();
}
private async static void TaskTest()
{
Console.WriteLine(Thread.CurrentThread.Name + "3");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "FirstTask";
Console.WriteLine(Thread.CurrentThread.Name + "4");
await Task.Delay(2000);
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "SecondTask";
Console.WriteLine(Thread.CurrentThread.Name + "5");
}
If you run this program you will see that await will use different thread. Output:
Main1
Main3
Main2
FirstTask4 // 2 seconds delay
SecondTask5 // 4 seconds delay
But if we remove both await keywords, you will learn that async alone doesn't do much. Output:
Main1
Main3
Main4
Main5
Main2

Categories