This entire post is about prerelease technologies. Everything is subject to change.
In one of the recent articles about CoreCLR, Daniel Roth mentions in passing “You can even make the main entry point asynchronous and return a Task.”
Yup, that’s right! Asynchronous
Main methods for Console applications! Let’s see how this works…
Getting Started with the CoreCLR CTP
If you want to follow along at home, first install the VS2015 CTP.
Next, you’ll need to install some K runtime stuff. The best instructions I’ve found for this are on the home page of the ASP.NET 5 GitHub repo. If you just want to get started quickly, open up PowerShell and execute the following commands:
Aside: How Many Runtimes?
It’s important to note that there are two K runtimes installed (well, four, if you count 32/64-bit variants). There’s the “ordinary” desktop CLR and the new CoreCLR. You can type
kvm list to show the installed runtimes and switch between them with
kvm upgrade -r coreclr and
kvm upgrade -r clr:
PS> kvm list Active Version Runtime Architecture Location Alias ------ ------- ------- ------------ -------- ----- 1.0.0-beta3 clr x64 C:\Users\stephen\.k\runtimes * 1.0.0-beta3 clr x86 C:\Users\stephen\.k\runtimes default 1.0.0-beta3 coreclr x64 C:\Users\stephen\.k\runtimes 1.0.0-beta3 coreclr x86 C:\Users\stephen\.k\runtimes PS> kvm upgrade -r coreclr Determining latest version kre-coreclr-win-x220.127.116.11-beta3 already installed. Adding C:\Users\stephen\.k\runtimes\kre-coreclr-win-x18.104.22.168-beta3\bin to process PATH Adding C:\Users\stephen\.k\runtimes\kre-coreclr-win-x22.214.171.124-beta3\bin to user PATH Updating alias 'default' to 'kre-coreclr-win-x126.96.36.199-beta3' PS> kvm list Active Version Runtime Architecture Location Alias ------ ------- ------- ------------ -------- ----- 1.0.0-beta3 clr x64 C:\Users\stephen\.k\runtimes 1.0.0-beta3 clr x86 C:\Users\stephen\.k\runtimes 1.0.0-beta3 coreclr x64 C:\Users\stephen\.k\runtimes * 1.0.0-beta3 coreclr x86 C:\Users\stephen\.k\runtimes default PS> kvm upgrade -r clr Determining latest version kre-clr-win-x188.8.131.52-beta3 already installed. Adding C:\Users\stephen\.k\runtimes\kre-clr-win-x184.108.40.206-beta3\bin to process PATH Adding C:\Users\stephen\.k\runtimes\kre-clr-win-x220.127.116.11-beta3\bin to user PATH Updating alias 'default' to 'kre-clr-win-x18.104.22.168-beta3' PS> kvm list Active Version Runtime Architecture Location Alias ------ ------- ------- ------------ -------- ----- 1.0.0-beta3 clr x64 C:\Users\stephen\.k\runtimes * 1.0.0-beta3 clr x86 C:\Users\stephen\.k\runtimes default 1.0.0-beta3 coreclr x64 C:\Users\stephen\.k\runtimes 1.0.0-beta3 coreclr x86 C:\Users\stephen\.k\runtimes
The regular desktop CLR is sitting on top of the full .NET framework. The CoreCLR is a new runtime. This is the one that a lot of people refer to as “cloud optimized” - though in reality, it’s just more of a microkernel-based framework as opposed to the traditional monolithic one. I expect we’ll see some great things from CoreCLR other than just running ASP.NET apps in the cloud (though it will of course be good for that too!) - the microkernel “only pay for what you use” architecture is perfectly suited for mobile platforms - and even smaller-than-mobile platforms!
Creating a CoreCLR Console Application
Let’s get started! In the CTP6, to create a CoreCLR console app, you choose New Project, and then…
Select “Web” on the left-hand side, and then “ASP.NET 5 Console Application”.
Yeah, “ASP.NET Console Application” is a ridiculous juxtaposition… This will probably be renamed completely as the tooling continues to develop. For now, though, the CoreCLR has strong roots in the ASP.NET world, so we create a CoreCLR Console application as an “ASP.NET Console” application.
Making It Asynchronous!
The default code the template gives you is pretty straightforward:
So let’s just rewrite it to be asynchronous:
Compile and run it, and you’ll see the Console application sticking around after the
Note the title bar. This console application is actually just a dll, which is hosted in the K runtime for the full desktop CLR. So this is actually running on whatever .NET desktop framework you have installed.
Running on the CoreCLR
To run on the actual CoreCLR, select the dropdown arrow of the Start button and choose the .NET Core as your CLR:
Then when you run it, you’ll be running on the CoreCLR (again, note the title bar):
Compiling for Multiple Frameworks
It’s important to peek under the covers a bit. Pop open your
project.json. See the
There are two frameworks for this project:
aspnet50 is the regular desktop CLR-based framework - it’s the one that runs on the full .NET desktop framework. The
aspnetcore50 is the CoreCLR framework - it’s the new microkernel one. Since CoreCLR is a microkernel architecture, you need to explicitly bring in nearly everything you intend to use - in this case, the VS template automatically added a dependency on
System.Console for you. (You can add more dependencies by installing NuGet packages;
System.Console is in fact just a NuGet package that is already installed into this project).
The important takeaway here is that this project is compiled twice, once for each framework. And there are APIs in each framework that the other doesn’t have. For example, I have a weird quirk where I strongly prefer using
ReadKey instead of
ReadLine in my throwaway Console applications. But CoreCLR’s
System.Console package doesn’t support
So, what happens if I change
ReadKey? At first, it looks OK, but it will no longer build.
The confusing part here is that there’s no “red squigglies” or anything indicating that
Console doesn’t have a
ReadKey method. Just an error that seems to come out of nowhere.
The key is to use the navigation bar - VS is aware that this file is compiled two different ways because our project is supporting two frameworks. By switching the view of the file to the CoreCLR, I can now see the error:
Note that the “Project” column of the Error List window specifies the framework as well as the project. This should be the first thing to check if you’re seeing “impossible” or mysterious errors like this.
Well, let’s say I really want to use
One solution is to make use of conditional compilation. Remember, this project is being compiled separately for each platform. As Rick Strahl pointed out, each platform defines a compiler directive that is just the platform name in all uppercase:
That works! So, you can use conditional compilation to take advantage of different APIs for different frameworks.
The conditional compilation does work, but it also causes a change in behavior between the frameworks. This is not ideal.
Instead, I’m going to decide that
ReadKey is just plain critical for my demos, and so CoreCLR is out. Thanks for playing.
To limit the frameworks for my project, I just have to edit the
project.json file and remove the CoreCLR:
Save the file, and now my project only targets the full desktop CLR.
aspnetcore50 framework will probably have to be done a lot over the next few months. There are a lot of third-party libraries that do not support the CoreCLR (yet).
Incidentally, I provided this technique as a Stack Overflow answer earlier today.
Currently, the “console application” we’re building is actually just a dll that’s hosted by a K runtime. I expect that when VS2015 gets to RTM, they’ll have a real executable popping out of the build. They have already started on something like that.
The old Console application type will undoubtedly stick around, for backwards compatibility at least. So, I’d expect VS2015 will have two Console application types: a legacy one that runs directly on the .NET Desktop Framework, and a new one that run on the K runtime (which in turn can run on either .NET Core CLR or .NET Desktop CLR). It’s the K runtime that gives us the power of an asynchronous entry point, so I’d expect only the new console application type would be able to have an
I just have to say that it’s so cool to get
async Main support! :)