I am new to asynchronous programming with the async
modifier. I am trying to figure out how to make sure that my Main
method of a console application actually runs asynchronously.
class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = bs.GetList();
}
}
public class Bootstrapper {
public async Task<List<TvChannel>> GetList()
{
GetPrograms pro = new GetPrograms();
return await pro.DownloadTvChannels();
}
}
I know this is not running asynchronously from "the top." Since it is not possible to specify the async
modifier on the Main
method, how can I run code within main
asynchronously?
You can solve this with this simple construct:
That will put everything you do out on the ThreadPool where you'd want it (so other Tasks you start/await don't attempt to rejoin a Thread they shouldn't), and wait until everything's done before closing the Console app. No need for special loops or outside libs.
Edit: Incorporate Andrew's solution for uncaught Exceptions.
In C# 7.1 you will be able to do a proper async Main. The appropriate signatures for
Main
method has been extended to:For e.g. you could be doing:
At compile time, the async entry point method will be translated to call
GetAwaitor().GetResult()
.Details: https://blogs.msdn.microsoft.com/mazhou/2017/05/30/c-7-series-part-2-async-main
EDIT:
To enable C# 7.1 language features, you need to right-click on the project and click "Properties" then go to the "Build" tab. There, click the advanced button at the bottom:
From the language version drop-down menu, select "7.1" (or any higher value):
The default is "latest major version" which would evaluate (at the time of this writing) to C# 7.0, which does not support async main in console apps.
In my case I had a list of jobs that I wanted to run in async from my main method, have been using this in production for quite sometime and works fine.
For asynchronously calling task from Main, use
Task.Run() for .NET 4.5
Task.Factory.StartNew() for .NET 4.0 (May require Microsoft.Bcl.Async library for async and await keywords)
Details: http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
Newest version of C# - C# 7.1 allows to create async console app. To enable C# 7.1 in project, you have to upgrade your VS to at least 15.3, and change C# version to
C# 7.1
orC# latest minor version
. To do this, go to Project properties -> Build -> Advanced -> Language version.After this, following code will work:
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.I have recent blog posts about async/await and asynchronous console programs in particular. Here's some background info from the intro post:
Here's why this is a problem in Console programs with an
async Main
: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 useAsyncContext
from my Nito.AsyncEx NuGet package.Here's an example using
AsyncContext
;GeneralThreadAffineContext
has almost identical usage:Alternatively, you can just block the main Console thread until your asynchronous work has completed:
Note the use of
GetAwaiter().GetResult()
; this avoids theAggregateException
wrapping that happens if you useWait()
orResult
.Update, 2017-11-30: As of Visual Studio 2017 Update 3 (15.3), the language now supports an
async Main
- as long as it returnsTask
orTask<T>
. So you can now do this: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.