Table of contents
Introduction
It has been almost a year since .NET 4.5 got released. But the problems with most of the recent Microsoft releases have been communication with .NET developers. Only one or two features are known to developers and other features just stay on MSDN and end up becoming simple documents.
For example, the time you ask a .NET developer what is new in the core framework .NET 4.5 most of them will just say async
and awaitt
(at least with people whom I have interacted have just talked about those features).
Again it’s very difficult to run through all the new features. Because the features may not sound interesting depending on what you are working currently on..
So in this article I have picked my five favorite features introduced in .NET 4.5 core. Again it’s possible my favorites cannot be your favorites. But what I have done is while choosing these features I kept in mind the larger .NET community and I hope I have met that expectation.
Note: This article does not discuss the new features in ASP.NET, WCF, WPF, WWF etc. It only talks about new features related to the core.
Feature 1: async and await (code markers)
This feature has been oversold and every .NET evangelist has talked about it. But this is still my favorite and you will come to know why in a few lines from here.
async
and await
are markers which mark code positions from where control should resume after a task (thread) completes.
Let us try to make sense of the above statement by understanding the below code. If you see the flow of the below code:
Method()
gets called from the Static void main()
entry point. Method()
spawns a Task
(thread) LongTask
which waits for 10 seconds. - At the same time the control comes back to
Method()
to execute the remaining code after the task was called. In other words as the invocation is multi-threaded (Task.Run
…), LongTask
is also running i.e., waiting for 10 seconds and the remaining code of your Method()
is also executed.
Now in certain scenarios we want step 3 to behave differently. We want that after LongTask()
finishes execution, the control should go back to Method
to execute the remaining code. The async
and await
keywords help to achieve the above behavior.
Now there are three important points to remember about the async
and await
keywords:
async
and await
are pair keywords. You cannot use them in a standalone manner. async
is marked on a method. This keyword is just an indicator saying that this method will have the await
keyword. - The
await
keyword marks the position from where the task should resume. So you will always find this keyword in conjunction with Task
.
Below is a modified version of the previously discussed code where we have applied async
and await
. All the other steps remain the same but “Step 3” is executed after “Step 2” completes. In simple words the control comes back to Method()
after the task has finished operation.
Now that you have read about “async” and “await”, let me put a cross question. The above behavior can be also achieved by using Task.Wait
or Task.ContinueWith
, so how do they differ? I am leaving this question as a home work for you.
Feature 2: Zip facility (Zip compression)
Zip is one of the most accepted archive file formats. Zip format is supported in almost all operating systems with some built-in name.
- In Windows operating system it’s implemented by the name “Compressed folders”.
- In MAC OS it’s implemented by the name “Archive utility”.
Now in .NET we did not have built-in support for implementing Zip compression. Many developers where using third party components like “DotnetZip”. In .NET 4.5, the Zip feature is baked in the framework itself, inside the namespace System.IO.Compression
.
The first step is you need to reference two namespaces:
System.IO.Compression.FileSystem
System.IO.Compression
The next step is to import the below two namespaces:
using System.IO.Compression;
If you want to Zip files from a folder you can use the CreateFromDirectory
function as shown below.
ZipFile.CreateFromDirectory(@"D:\data",@"D:\data.zip");
If you wish to unzip, you can use the ExtractToDirectory
function as shown in the below code.
ZipFile.ExtractToDirectory(@"D:\data.zip", @"D:\data\unzip");
Feature 3: Regex timeout (TimeOut)
“Regex” has been the most preferred way of doing validations. In case you are new to Regex, please see the Regex video where I have explained how regex is implemented. But because of the typical parsing logic of regex it is exposed to DOS attacks. Let us try to understand in detail what I mean by that.
For instance consider this regular expression - “^(\d+)$”. This regex expression says that it can have only numbers. You can also see the regex symbolic diagram which shows how the regex will be evaluated .Now let’s say if we want to validate “123456X”. It will have six paths as shown in the below figure.
But if we add one more number to it, it will take seven paths. In other words as the length increases a regex takes more time to evaluate. In other words the time taken to evaluate is linearly proportional to the length of the characters.
Now let’s complicate the previously defined regex from “^(\d+)$” to “^(\d+)+$” . If you see the regex symbolic diagram it’s pretty complex. If we now try to validate “123456X”, it will run through 32 paths. If you add one more character the number pf paths become 64.
In other words for the above regex, the time taken to evaluate rises exponentially with the number of characters.
Now the question you would ask is, how does it matter? This linear rise of evaluation time can be exploited by hackers to do a DOS (Denial of Service) attack. They can put a long, a really long string and make your application hang forever.
The proper solution for this would be to have a timeout on the regex operation. Good news, in .NET 4.5 you can now define a timeout property as shown in the below code. So if you get any kind of malicious string, the application will not go in a loop forever.
try
{
var regEx = new Regex(@"^(\d+)+$", RegexOptions.Singleline, TimeSpan.FromSeconds(2));
var match = regEx.Match("123453109839109283090492309480329489812093809x");
}
catch (RegexMatchTimeoutException ex)
{
Console.WriteLine("Regex Timeout");
}
Below is a nice video which is uploaded on Facebook which demonstrates the DOS attack by regular expression and how it can be prevented using regex timeout feature of .NET 4.5. Do not miss it, worth a watch.
Feature 4: Profile optimization (Improved startup performance)
We all know .NET code is in a half compiled format. During runtime, the JIT (Just-in-Time) compiler runs and translates this half compiled IL code to native machine code. One of the big complaints about JIT is that when a .NET applications runs the first time, it runs slow as JIT is busy translating IL code to machine code.
In order to bring down this startup time, in .NET 4.5, we have something called “profile optimization”. Profile is nothing but a simple file which has a list of methods which the application will need during startup. So when the application starts, a background JIT runs and starts translating IL code for those methods into machine / native code.
This background JIT compilation of startup methods happens across multiple processors thus minimizing the start up time further. Also note you need to have a multicore box to implement profile optimization. In case you do not have a multicore box then this setting is ignored.
In order to create the “profile” file, you first need to import the System.Runtime
namespace. You can then call the SetProfileRoot
and StartProfile
methods of the static class ProfileOptimization
. Now when the application starts the background JIT it will read from the profile file and compile your start up methods in the background thus reducing your startup time.
using System.Runtime;
ProfileOptimization.SetProfileRoot(@"D:\ProfileFile");
ProfileOptimization.StartProfile("ProfileFile");
One important note: Profileoptimization
is enabled by default for ASP.NET 4.5 and Silverlight 5 applications. So the above code need not be written for these technologies.
Feature 5: Garbage collector (GC background cleanup)
Garbage collector is one real heavy task in a .NET application. And it becomes heavier when it is an ASP.NET application. ASP.NET applications run on the server and a lot of clients send requests to the server thus creating loads of objects, making the GC really work hard for cleaning up unwanted objects.
In .NET 4.0, when the GC runs for cleanup, all the application threads are suspended. You can see in the above figure we have three application threads running. We have two GCs running on separate threads. One GC thread for one logical processor. Now the application threads run and do their work. Now as these application threads are performing their task they also create managed objects.
At some point of time the background GC runs and starts clean up. When these background GCs start cleanup, they suspend all the application threads. This makes the server/application less responsive for that moment.
To overcome the above problem, server GC was introduced. In server GC there is one more thread created which runs in the background. This thread works in the background and keeps cleaning generation 2 (see this video for GC generation 0, 1, and 2)objects thus minimizing the load on the main GC thread. Due to double GC threads running, the main application threads are less suspended, thus increasing application throughput. To enable server GC, we need to use the gcServer
XML tag and enable it to true
.
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
Three more features worth exploring
Set default culture to App Domain
In the previous versions of .NET if I needed to set culture I needed to do it in every thread. Below is a sample code which demonstrates the pain of setting culture at thread levels. That was a real pain when we had heavily multi-threaded applications.
CultureInfo cul = new CultureInfo(strCulture);
Thread.CurrentThread.CurrentCulture = cul;
Thread.CurrentThread.CurrentUICulture = cul;
In 4.5 we can set culture at the app domain level and all the threads inside that appdomain will inherit that culture. Below is a sample code of how to implement DefaultThreadCurrentCulture
.
CultureInfo culture = CultureInfo.CreateSpecificCulture("fr-FR");
CultureInfo.DefaultThreadCurrentCulture = culture;
Array support more than two gigabyte size
I am not sure in what kind of a scenario we would need a 2 GB collection. So I personally do not see where we would need this feature. If I ever need such a big collection I would break it into parts. But I am sure there should be a good reason for this feature to be enabled in the framework.
Unicode support for console
I left this feature out from the discussion as very less people work with console applications. I have seen people using consoles for academic purposes. All said and done we now have Unicode support for console apps also.
References
<movie height="360" width="630">
For further reading do watch the below interview preparation videos and step by step video series.