This question already has answers here:
Can't specify the 'async' modifier on the 'Main' method of a console app
(20 answers)
Closed 5 years ago.
I have this simple code:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Great. This compiles.
But let’s say I have a console application and I want to run the code above (calling SumTwoOperationsAsync()).
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
But I've read that (when using sync) I have to sync all the way up and down:
Does this mean that my Main function should be marked as async?
Well, it can't be because there is a compilation error:
an entry point cannot be marked with the 'async' modifier
If I understand the async stuff , the thread will enter the Main function → SumTwoOperationsAsync → will call both functions and will be out. But until the SumTwoOperationsAsync
What am I missing?
In most project types, your async "up" and "down" will end at an async void event handler or returning a Task to your framework.
However, Console apps do not support this.
You can either just do a Wait on the returned task:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
or you can use your own context like the one I wrote:
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
More information for async Console apps is on my blog.
Here is the simplest way to do this
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
As a quick and very scoped solution:
Task.Result
Both Task.Result and Task.Wait won't allow to improving scalability when used with I/O, as they will cause the calling thread to stay blocked waiting for the I/O to end.
When you call .Result on an incomplete Task, the thread executing the method has to sit and wait for the task to complete, which blocks the thread from doing any other useful work in the meantime. This negates the benefit of the asynchronous nature of the task.
notasync
My solution. The JSONServer is a class I wrote for running an HttpListener server in a console window.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}
Related
I have four methods.
Main: only calls the preform method
Working: displays "please wait for the user"
Taking Time: A program that takes time to execute.
Preform: Calls the taking time and working methods asynchronously.
The following is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncObservation
{
class Program
{
static void Main(string[] args)
{
preform();
}
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
Thread.Sleep(1000);
Console.WriteLine("The Program finished");
}
public static async void preform()
{
Task timer = Takingtime();
Task wait = Working();
}
}
}
In the end: I need to display
This program started.
Please wait, the program is running
The program ended.
I see several problems in your program.
Although Preform is neither async nor an event handler, it does not return a Task
The tasks started in Preform are not awaited for before you finish Preform. Hence you never know when they are finished, nor what the results are (exception?). You could even end your program before they are finished
After you start a Task it is not guaranteed when it will run. You can only be sure that statements are already executed if you await for the Task.
Using async-await is a method to make sure that your thread looks around to see if it can do useful stuff instead of waiting idly if it has to wait for something. Thread.Sleep is a busy wait. If you want to look around to see if you can do something else use await Task.Delay(TimeSpan.FromSeconds(1)) instead.
In your case, you can't be sure that any Console line has been written until you await the procedure that should write your line. If you start your second Task before awaiting the first, you don't know how far the first task already proceeded, and thus you don't know for sure that the text already has been written to the Console.
C# 7.1 introduced async Task Main(), so you could use that instead of the traditional void Main. It saves you from catching and interpreting the AggregateException that is thrown by the Task you start to make your process async.
If you don't want to use the async Main, you can of course use Task.Run to call an async function:
static void Main(string[] args)
{
try
{
var preformTask = Task.Run( () => Preform() );
DoSomethingElse(); // if needed
preformTask.Wait(); // wait for preformTask to finish
Console.WriteLine("Task completed; press any key to finish");
Console.ReadKey();
}
catch (Exception exc) // inclusive ggregateException if one of your Task fails
{
ProcessException(exc)
}
}
static async Task preform()
{
// To be certain that the Console Line has been written: await
await Takingtime();
// if here, you are certain that the Line has been written,
// or course you have lost parallel processing
await Working();
}
For completeness: the other functions
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
// either return a completed Task, or await for it (there is a difference!
await Task.CompletedTask;
// or:
return Task.CompletedTask; // do not declare async in this case
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
//Use Task.Delay instead of Sleep
await Task.Delay(TimeSpan.FromSeconds(1); // improved readability
Console.WriteLine("The Program finished");
}
Because of the awaits in Preform you are certain that the text has been written. However, you've lost some parallellism.
If you really want those procedures to execute at the same time, you can't be certain about when text will be written. If that is important, then split the Parts that should be run first (write Console) from the parts that should run in parallel (Task.Delay)
static async Task preform()
{
// Do the things that should be done before parallel tasks are run
await DoThisFirst();
// start the Tasks that can work parallel: not sure what statements are executed first
var taskA = DoTaskA();
var taskB = DoTaskB();
// if here, you are free to do something else
// can't be sure about the status of taskA nor taskB
DoSomethingElse();
// if you want to do something after you know that the tasks have completed:
// await the tasks here:
await Task.When (new Task[] {taskA, taskB});
// if here, you are certain that all parallel tasks have completed successfully
// if desired fetch the return values of the Tasks:
var returnValueA = taskA.Result;
var returnValueB = taskB.Result;
// do all async things of which you needed to be certain that both tasks finished
// for example:
await ProcessResults(returnValueA, returnValueB);
}
In a console app it is OK to use a .Wait() call in an void Main method.
In some contexts where there is synchronisation necessary .Wait() can cause deadlocks (ASP.NET has a request to synchronise on or XAML/WinForms which have a UI thread), but there is nothing to synchronise on here.
static void Main()
{
preform.Wait()
}
This will wait for the async work to complete synchronously. You need the method to run synchronously so that it does not return early. If you use async void and await the method will return immediately and exit the method, await does not work in a Main method.
I would also suggest using await Task.Delay(1000); rather than Thread.Sleep(1000); as this is the canonical async way to idle.
For your code example:
class Program
{
static void Main(string[] args)
{
preform().Wait();
Console.ReadLine();
}
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
await Task.Delay(1000);
Console.WriteLine("The Program finished");
}
public static Task preform()
{
return Task.WhenAll(
Takingtime(),
Working());
}
}
Use Stephen Cleary's Nito.AsyncEx library (available via Nuget) to provide an asynchronous context for a console application. See here for more details.
Your application can then be written as ...
class Program
{
static int Main(string[] args)
{
try
{
Console.WriteLine("The application has started");
AsyncContext.Run(() => LongRunningTaskAsync(args));
Console.WriteLine("The application has finished");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return -1;
}
}
static async Task LongRunningTaskAsync(string[] args)
{
Console.WriteLine("The long running task has started");
// use Task.Delay() rather than Thread.Sleep() to avoid blocking the application
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
Console.WriteLine("The long running task has finished");
}
}
Use preform().Wait() in the constructor. So the call is awaited. Then use await Takingtime() and await Working() in the preform method.
And you have to change the return type to Task.
I am rather new to task based programming and trying to determine how to return a task and verify that it has been started. The code that I got to work was not what I was expecting. The console application is as follows:
public static void Main(string[] args)
{
var mySimple = new Simple();
var cts = new CancellationTokenSource();
var task = mySimple.RunSomethingAsync(cts.Token);
while (task.Status != TaskStatus.RanToCompletion)
{
Console.WriteLine("Starting...");
Thread.Sleep(100);
}
Console.WriteLine("It is started");
Console.ReadKey();
cts.Cancel();
}
public class Simple
{
public async void RunSomething(CancellationToken token)
{
var count = 0;
while (true)
{
if (token.IsCancellationRequested)
{
break;
}
Console.WriteLine(count++);
await Task.Delay(TimeSpan.FromMilliseconds(1000), token).ContinueWith(task => { });
}
}
public Task RunSomethingAsync(CancellationToken token)
{
return Task.Run(() => this.RunSomething(token));
}
}
The output is:
Starting...
0
It is started
1
2
3
4
Why is the task that is being returned have a status as TaskStatus.RanToCompletion compared to TaskStatus.Running as we see that the while loop is still executing? Am I checking the status of the task of putting the RunSomething task on the threadpool rather than the RunSomething task itself?
RunSomething is an async void method, meaning it exposes no means of the caller ever determining when it finishes, they can only ever start the operation and then have no idea what happens next. You then wrap a call to it inside of Task.Run, this is schedluing a thread pool thread to start RunSomething. It will then complete as soon as it has finished starting that Task.
If RunSomething actually returned a Task, then the caller would be able to determine when it actually finished, and if you waited on it it wouldn't actually indicate that it was done until that asynchronous operation was actually finished (there would be no reason to use Task.Run to start it in another thead, you'd be better off just calling it directly and not wasting the effort of moving that to a thread pool thread).
Never use async void (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx)
instead you should use async Task
If you need to call an async method from a non-async (such as from a static void main) you should do something like this:
mySimple.RunSomethingAsync(cts.Token).GetAwaiter().GetResult();
That will effectively make the method a synchronous call.
You can use async void, but only for events.
I have a console app and I want to launch tasks one after the other.
Here is my code:
static void Main()
{
string keywords = "Driving Schools,wedding services";
List<string> kwl = keywords.Split(',').ToList();
foreach(var kw in kwl)
{
Output("SEARCHING FOR: " + kw);
Task t = new Task(() => Search(kw));
t.Start();
t.Wait();
}
Console.ReadLine();
}
static async void Search(string keyword)
{
// code for searching
}
The problem is that it doesn't wait for the first task to finish executing. It fires off the subsequent tasks concurrently.
I am working with a rate limited API so I want to do one after the other.
Why is it not waiting for one search to finish before starting the next search?
Your async method just returns void, which means there's no simple way of anything waiting for it to complete. (You should almost always avoid using async void methods. They're really only available for the sake of subscribing to events.) Your task just calls Search, and you're waiting for that "I've called the method" to complete... which it will pretty much immediately.
It's not clear why you're using async at all if you actually want to do things serially, but I'd suggest changing your code to look more like this:
static void Main()
{
// No risk of deadlock, as a console app doesn't have a synchronization context
RunSearches().Wait();
Console.ReadLine();
}
static async Task RunSearches()
{
string keywords = "Driving Schools,wedding services";
List<string> kwl = keywords.Split(',').ToList();
foreach(var kw in kwl)
{
Output("SEARCHING FOR: " + kw);
await Search(kw);
}
}
static async Task Search(string keyword)
{
// code for searching
}
I have a while-loop that should repeat the program until a certain condition is met. Inside this loop I call an async function, which prints out a message for me. Here is the (cut-short) code:
private void InitializeMessageSystem ( )
{
do
{
// Do stuff
await printMessage ("Hello World!");
Console.ReadKey();
} while (condition != true)
}
And here the function PrintMessage():
private static async Task PrintMessage (string message, int spd = 1)
{
int delay = 50 / spd;
string[] words = message.Split(' ');
int index = 1;
for (int word = 0; word < words.Length; word++)
{
char[] current = words[word].ToCharArray();
if (index + current.Length > Console.WindowWidth)
{
Console.WriteLine();
index = 1;
}
for (int c = 0; c < current.Length; c++)
{
Console.Write(current[c]);
await Task.Delay(delay);
}
Console.Write(" ");
}
}
Edit: Here's the call from the main function:
static void Main (string[] args)
{
InitializeMessageSystem();
Console.ReadKey();
}
Question
Why does my program exit, when I press a key while the function is not yet completed? I thought the program would wait for the Console.ReadKey() until the function PrintMessage() is completed?
Your problem is that await returns the control flow of the program to the caller of the function. Normally execution is continued at that point when the asynchronous task you await finishes.
So control is returned to your main function as you wait for printMessage and main now waits for a key input. As you hit the key main returns to the OS and your process (including all asynchronous tasks) terminates.
Change your InitializeMessageSystem to
private async Task InitializeMessageSystem ( )
and change the code in main to
InitializeMessageSystem().Wait();
to wait until InitializeMessageSystem finishes completely before waiting for the key.
The below code executes without any errors or warnings. But when you execute the code the program exits silently. What you might be expecting is the program waits for the task to complete, asks the user to press any key and exit. What actually happens is after the await statement is executed the control goes back to the invoking step. In our case after the step await task; is executed, before the task completes the control goes back to the invoking step SomeTask(); and the program exits.
class Program
{
static void Main(string[] args)
{
SomeTask();
}
public static async void SomeTask()
{
Task task = Task.Run(() =>
{
System.Threading.Thread.Sleep(20000);
Console.WriteLine("Task Completed!");
});
await task;
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
To fix this, add await to the SomeTask(); call so that the program waits for async SomeTask() to complete. You should also change the return type
of SomeTask() from void to Task.
class Program
{
static void Main(string[] args)
{
await SomeTask();
}
public static async Task SomeTask()
{
Task task = Task.Run(() =>
{
System.Threading.Thread.Sleep(20000);
Console.WriteLine("Task Completed!");
});
await task;
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
The difference between calling a synchronous function and an async function is that when calling the synchronous function you know that when you reach the statement after the call the function is executed completely. When calling an async function, the function is scheduled as a task at the thread pool to be performed when any of the threads in the pool has time for it.
This gives you time to do other things while one of the threads is performing the task. As soon as you need the result you await for the task to be finished.
This works only if your function is also async. If you don't make your function async your can't use async-await. Making your function async and the clients of your function also async is the only way to truly use async-await. Remember: all async functions should return Task instead of void and Task<TResult> instead of TResult. The only exception is the event handler
private async void Button1_Clicked(object sender, ...)
{
var myTask = SlowMultiplierAsync(4, 3);
// while myTask is running you can do other things
// after a while you need the result:
int taskResult = await myTask;
Process(taskResult);
}
private async Task<int> SlowMultiplierAsync(int x, int y)
{
// let's take a nap before multiplying
// do this by awaiting another async function:
await Task.Delay(TimeSpan.FromSeconds(5));
return x * y;
}
If you don't want (or can) make your function async, you can simulate similar behaviour by starting a task using task.Run:
private void InitializeMessageSystem ( ) {
do
{
// Do stuff
var myTask = task.Run( () => printMessage ("Hello World!"));
myTask.Wait();
Console.ReadKey();
} while (condition != true)
Although this will make sure that your function won't end before the task is finished, your function will be a synchronous one for your clients. For instance it won't make your UI responsive.
Eric lippert here on stackoverflow once explained me the difference between asynchronous concurrent. Link to his answer
Suppose you have to make breakfast. Toast some bread and cook some eggs.
Synchronous: start toasting bread. Wait until toasting finished. Start cooking eggs, wait until eggs are cooked.
Asynchronous but not concurrent: start toasting bread, and while the bread is toasting start cooking eggs. While the eggs are cooking yo can do other things, like making tea. After a while you wait until the eggs are cooked and wait until the bread is toasted. This is typically async-await.
Asynchronous and concurrent: hire a cook to toast the bread, hire a cook to cook the eggs and wait until both cooks are finished. Here the toasting and cooking is done by different threads. It is the most expensive method
I have written the following (a plain Console application) to test my understanding about async and await in C#.
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Async result: " + getLengthFromWebsiteAsync());
}
public static async Task<int> getLengthFromWebsiteAsync()
{
HttpClient httpClient = new HttpClient();
Task<string> sampleTask = httpClient.GetStringAsync("http://www.adobe.com");
Console.WriteLine("Before the await: ");
int lengthRequired = (await sampleTask).Length;
Console.WriteLine("After the await: " + lengthRequired.ToString());
return lengthRequired;
}
The following is the result that I got upon running:
Before the await:
Async result: System.Threading.Tasks.Task'1[System.Int32]
My question is, isn't the line "After the await: " supposed to show up? Am I on the wrong track in understanding the flow of async/await?
Currently you're starting the operation - but it's never completing. Your program is terminating before you do anything with the task.
As this is a console app, continuations will run on a thread-pool thread anyway, so you can change your code to make the Main method block until the task has completed:
public static void Main(string[] args)
{
Console.WriteLine("Async result: " + getLengthFromWebsiteAsync().Result);
}
Normally you should be very careful about using Result and Wait() on tasks, as you can easily cause a deadlock. (For example, it wouldn't be safe to do the above in a WinForms UI - the Result call would block the UI thread until the task completed... and the task would be waiting for the UI thread to become available to run the continuation after the await in the async method.)