Can't specify the 'async' modifier on the 'Main' method of a console app
As you discovered, in VS11 the compiler will disallow an async Main
method. This was allowed (but never recommended) in VS2010 with the Async CTP.
Update, 2017-11-30: As of Visual Studio 2017 Update 3 (15.3), the language now supports an async Main
- as long as it returns Task
or Task<T>
. So you can now do this:
class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
The semantics appear to be the same as the GetAwaiter().GetResult()
style of blocking the main thread. However, there's no language spec for C# 7.1 yet, so this is only an assumption.
I have recent blog posts about async/await and asynchronous console programs in particular. Here's some background info from the intro post:
If "await" sees that the awaitable has not completed, then it acts asynchronously. It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method. Await will also capture the current context when it passes the remainder of the method to the awaitable.
Later on, when the awaitable completes, it will execute the remainder of the async method (within the captured context).
Here's why this is a problem in Console programs with an async Main
:
Remember from our intro post that an async method will return to its caller before it is complete. This works perfectly in UI applications (the method just returns to the UI event loop) and ASP.NET applications (the method returns off the thread but keeps the request alive). It doesn't work out so well for Console programs: Main returns to the OS - so your program exits.
One solution is to provide your own context - a "main loop" for your console program that is async-compatible.
If you have a machine with the Async CTP, you can use GeneralThreadAffineContext
from My Documents\Microsoft Visual Studio Async CTP\Samples(C# Testing) Unit Testing\AsyncTestUtilities. Alternatively, you can use AsyncContext
from my Nito.AsyncEx NuGet package.
Here's an example using AsyncContext
; GeneralThreadAffineContext
has almost identical usage:
using Nito.AsyncEx;
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => MainAsync(args));
}
static async void MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
Alternatively, you can just block the main Console thread until your asynchronous work has completed:
class Program
{
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
Note the use of GetAwaiter().GetResult()
; this avoids the AggregateException
wrapping that happens if you use Wait()
or Result
.
C#: call async method inside Main of console application leads to compilation failure
Your Main
method doesn't comply with one of the valid signatures listed here.
You probably want to use this:
public static async Task Main(string[] args)
A Task
needs to be returned, so that the runtime knows when the method is complete; this couldn't be determined with void
.
The compiler achieves this by generating a synthetic entry point:
private static void $GeneratedMain(string[] args) =>
Main(args).GetAwaiter().GetResult();
Cannot create an async Main
Your visual studio by default will be setted to this
Which means that the major version will be 7.0 and not 7.1 you should force it to 7.1 in order to compile it with the 7.1 version
The second option in Project Properties=> Build =>advanced set the language version to C# latest minor version(latest)
Using 'async' in a console application in C#
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.
An entry point cannot be marked with the 'async' modifier
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.
C# - Use Async in Main function
async Task Main
is available in C# 7.1. You can change it in build properties (the default is the latest major version, which is 7.0)
Asynchronous method does not work well in Console application
Your program finishes before the Wait
and terminates (including the "wait" method). You need to await the task returned by Delay
somewhere. To have desired output you can do it like that, for example (using C# 7.1 async Main
feature):
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("*** Main Method Start ***");
var t = Operation();
Console.WriteLine("*** Main Method End ***");
await t;
}
static Task Operation()
{
Console.WriteLine("*** Operation Method Start ***");
var task1 = Delay(5000);
Console.WriteLine("*** Operation Method End ***");
return task1 ;
}
static async Task<int> Delay(int ms)
{
Console.WriteLine($"Start {ms}(ms) Delay");
await Task.Delay(ms);
Console.WriteLine($"End {ms}(ms) Delay");
return ms;
}
}
Related Topics
Dynamic Linq Orderby on Ienumerable≪T≫/Iqueryable≪T≫
Is There a Constraint That Restricts My Generic Method to Numeric Types
How to Get a Consistent Byte Representation of Strings in C# Without Manually Specifying an Encoding
Validate a Username and Password Against Active Directory
Encrypting & Decrypting a String in C#
Parameterized Query For MySQL With C#
In C#, Should I Use String.Empty or String.Empty or "" to Intitialize a String
How to Read a Text File Reversely With Iterator in C#
Can You Call Directory.Getfiles() With Multiple Filters
How to Check If a File Is in Use
C# Variance Problem: Assigning List≪Derived≫ as List≪Base≫
Create Generic Method Constraining T to an Enum
How to Create a Dropdownlist from an Enum in ASP.NET MVC
How to Convert a Column Number (E.G. 127) into an Excel Column (E.G. Aa)
How to Get the Webbrowser Control to Show Modern Contents
How to Fix the Flickering in User Controls
Cannot Convert from List≪Derivedclass≫ to List≪Baseclass≫