Wednesday, July 10, 2013

Demystifying .NET 4.5 "in-place" update

A lot has been said on the Internet about .NET Framework 4.5 being an "in-place" update for .NET Framework 4.0. I'm not sure where it all started from, but it has definitely made huge impact on the community. So if you have .NET 4.0 installed and then you install .NET 4.5, you are not able to use the old framework anymore? That's what a lot of people believe. Which creates a lot of confusion and postings like this: http://stackoverflow.com/questions/11458159/how-to-keep-net-4-0-behavior-if-net-4-5-is-installed

We have a Windows Form application that targets .Net Framework 4.0. After installing .Net Framework 4.5, the application starts crashing. We'll have to investigate the crashes and we'll most probably have to fix things on our side. But is there a setting we can turn on to keep the old behavior until we are ready to use .Net 4.5?

Of course. You install a new version of the framework and it breaks all of your applications. Poor guy... Or course I wouldn't mention this posting here if it didn't have this in the end of the discussion:

I discussed this over email with original question poster - "Sly". Thanks Sly for helping investigate. It turns out that .NET4 and .NET4.5 behave the same way for Dispose(waithandle) API. So this problem is potentially unrelated to .NET4.5.

Oh that's really good news. At least I don't have to uninstall .NET 4.5 from my machine.

A lot of people, not only on the Internet, think that installing .NET 4.5 on your local machine or even on your servers will automatically make your applications take advantage of the new features, probably improve performance or just break your applications. Depending on lucky you are.

I didn't take it seriously in the beginning but at some point I have decided to really think about it. Can Microsoft create such a trap for its users? How can that possibly be true? So I have done a little investigation myself.

In our investigation we will try to answer these questions:
  • Can we still use .NET 4.0 after "in-place" update of .NET 4.5 was installed?
  • Will our application automatically start using .NET 4.5?
  • How does the system decide which version of .NET it should execute our application with?
At first let's think about how we can find which framework version our application is using at the moment. There are several ways in .NET to find the CLR version the app is being executed with. Which are often mistakenly assumed to be return the .NET version. For example see this topic: http://stackoverflow.com/questions/8517159/how-to-detect-at-runtime-that-net-version-4-5-currently-running-your-code

Unfortunately there is no universal proper way to determine the .NET version. The best we can do is to load some of the standard .NET assemblies and check its version. But this method is also not ideal because some assemblies may be present in one version of the framework but not in another one. And there are other catches besides that.

Let's try simpler approach and find the framework version by executing some code that behaves differently in  .NET 4.0 and 4.5. This MSDN page contains a list of .NET 4.5 breaking changes: http://msdn.microsoft.com/en-us/library/hh367887.aspx

Let's pick some breaking change that is easy to verify, for example:

In applications that target the .NET Framework 4.5, trailing dots at the end of a path segment in an original URI string (for example, http://www.proseware.com/LLC./About.aspx) are preserved. (Note that path segments that consist exactly of one or two dots, such as http://www.proseware.com/.. orhttp://www.proseware.com/./default.htm, are removed, but path segments that have more than two consecutive dots (such as http://localhost/dir1/.../dir2) are preserved.

Which means we can write a simple program to check if we are running on .NET 4.5:
using System;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Environment.Version);

            const string originalUrl = "http://localhost/dir1/.../dir2";

            Uri uri = new Uri(originalUrl);

            string convertedUri = uri.ToString();

            Console.WriteLine(convertedUri);

            Console.WriteLine(convertedUri == originalUrl ? "4.5" : "something else");
        }
    }
}

Here we create a string URI with three consecutive dots. If after creating a Uri object and converting it back to string we get the same three dots, it means we are on .NET 4.5. Otherwise, if dots are not preserved we are using a different framework version.

Let's compile this program in Visual Studio 2012 with all the default project settings and run it. On my machine it gives the following output (first line is just a CLR version):

4.0.30319.18046
http://localhost/dir1/.../dir2
4.5

The result is expected. All three dots are preserved. Now let's look at our assembly in ildasm and see if we can find any clues as to which version of the framework to use. For that let's just type in VS2012 command line (while in the debug directory):

ConsoleApplication3\bin\Debug>ildasm ConsoleApplication3.exe 

In the opened window let's click on the manifest tree view item to find the following text among other information:

  .custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
                                                                                                        2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54   // ,Version=v4.5..T
                                                                                                        0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C   // ..FrameworkDispl
                                                                                                        61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D   // ayName..NET Fram
                                                                                                        65 77 6F 72 6B 20 34 2E 35 )                      // ework 4.5

Interesting. Some TargetFrameworkAttribute. Now let's try and change the Target Framework in our project properties to .NET 4.0. Rebuild it, run ildasm again and we will get...

.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ....NETFramework
                                                                                                        2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 01 00 54   // ,Version=v4.0..T
                                                                                                        0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C   // ..FrameworkDispl
                                                                                                        61 79 4E 61 6D 65 10 2E 4E 45 54 20 46 72 61 6D   // ayName..NET Fram
                                                                                                        65 77 6F 72 6B 20 34 )                            // ework 4

Same thing but the version has been changed to 4.0 which is expected.

Now that out project is build with .NET 4.0 let's run it again:

4.0.30319.18046
http://localhost/dir1/dir2
something else

It's a different output! Which means the MSDN was right saying that this is a breaking change. (Note, however, that we have the same version of the CLR which just illustrates that CLR version and .NET version are totally different things)

So far so good. At least we are able to use the old framework with the new framework installed.

As we can see, selecting a different framework version in Visual Studio changes the TargetFrameworkAttribute value in the assembly manifest. Which probably means Visual Studio adds this attribute automatically. To verify our assumption let's try a little experiment. Add the TargetFrameworkAttribute attribute in the program code by hand:

using System;

[assembly: System.Runtime.Versioning.TargetFramework(".NETFramework,Version=v4.5")]

namespace ConsoleApplication3
{
    class Program

Now if we try to build it...

Error 4 Duplicate 'System.Runtime.Versioning.TargetFramework' attribute

Boom. Compilation error. Which actually makes sense. If Visual Studio adds the same attribute itself, that would be weird if we could add it as well. For example if in the project properties we have Target Framework Version set to 4.0 but in our code we add the TargetFrameworkAttribute for 4.5, who should win in this situation? No one. Visual Studio will just give us a nice error saying it's a duplicate attribute.

Okay. So Visual Studio always adds the TargetFrameworkAttribute based on the project settings. But do we have to build our project in Visual Studio? Of course not! We can just use C# compiler "csc.exe". So let's go to the folder containing our program code (Program.cs) and compile it from the command line:

ConsoleApplication3>csc Program.cs

It compiles successfully. And if we open the resulting assembly "Program.exe" in ildasm we will see the same TargetFrameworkAttribute that we set in our code. Which is exactly what we expected. Needless to say, if we run this program it will output the correct .NET framework version which is 4.5.

Great. We can add the TargetFrameworkAttribute in our code if compiling with csc.exe but then we may have another question. What if we don't add this attribute and still compile with csc.exe? What will be in the manifest in this case? We don't set it ourselves in the code and we also don't have Visual Studio to set it for us. Any guesses? Let's try that.

 ... And there is nothing in the metadata saying which framework version to use! Crazy. So the only thing we can do is try and run our program and see the output:

4.0.30319.18046
http://localhost/dir1/dir2
something else

Wow! The same output as for the .NET 4.0-targeted program. What does that mean for us? In the absence of the TargetFrameworkAttribute it doesn't even use the latest version of the framework installed. What a surprise. Actually I don't have an answer to this question. How it selects framework version in this case is still to be figured out. Maybe there is some registry setting for that.

I have tried running the program on three different machines (Windows 7, Windows 8, Windows Server 2012) and they all gave me the same results (only CLR version was a bit different in last several digits).

So to summarize and answer the question we asked:
  • Yes, we still can use the .NET 4.0 even after 4.5 is installed.
  • No, existing applications don't magically start using .NET 4.5. If they are built with Visual Studio or similar tools (e.g. msbuild), the manifest will contain the TargetFrameworkAttribute with the framework version specified in the project properties. Even if we don't use Visual Studio tools we can specify that attribute directly in code. In either case the value specified in the attribute will be used at run time as a framework version.
  • If there is no TargetFrameworkAttribute specified, version 4.0 is used (or maybe even some other version but definitely not 4.5). How this is determined is unknown. But this question requires its own investigation.

Friday, May 17, 2013

C# 5 - The Power Of Async

Let's assume we have a WCF service that has a method to get some data.
For example, it returns a Product object

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public long Price { get; set; }
        public string Category { get; set; }
    }

    [ServiceContract]
    public interface IProductService
    {
        [OperationContract]
        Product GetProduct(int id);
    }

 But to get product information we need to make calls to some external systems (query the database or make a call to another web service etc.). For the sake of simplicity, let's say we have one external web service that we need to call to get product Name, Price and Category:

    [ServiceContract]
    public interface IExternalService
    {
        [OperationContract]
        string GetProductCategory(int id);

        [OperationContract]
        long GetProductPrice(int id);

        [OperationContract]
        string GetProductName(int id);
    }

So to get full product information we need to make three calls to the external service.
The problem with the external service is that it's a bit slow. Here is the implementation:

    public class ExternalService : IExternalService
    {
        public string GetProductCategory(int id)
        {
            Thread.Sleep(1000);

            return "Category " + id;
        }

        public long GetProductPrice(int id)
        {
            Thread.Sleep(2000);

            return id * 1000;
        }

        public string GetProductName(int id)
        {
            Thread.Sleep(1500);

            return "Name " + id;
        }
    }

 As you can see, all operations are delayed for 1-2 seconds for illustrative purposes to simulate a busy system.

So how do we call the external service from our ProductService? If we make three calls sequentially, that will be really slow (4.5 seconds). How can we improve this time? Let's make three calls in parallel, then collect the results and return the product back to the client:

    public class ProductService : IProductService
    {
        public Product GetProduct(int id)
        {
            var p = new Product();

            var nameTask = new Task(() => { p.Name = GetProductName(id); });
            var priceTask = new Task(() => { p.Price = GetProductPrice(id); });
            var categoryTask = new Task(() => { p.Category = GetProductCategory(id); });

            nameTask.Start();
            priceTask.Start();
            categoryTask.Start();

            Task.WaitAll(nameTask, priceTask, categoryTask);

            return p;
        }

        private string GetProductCategory(int id)
        {
            return new ExternalServiceClient().GetProductCategory(id);
        }

        private long GetProductPrice(int id)
        {
            return new ExternalServiceClient().GetProductPrice(id);
        }

        private string GetProductName(int id)
        {
            return new ExternalServiceClient().GetProductName(id);
        }
    }

Looks good. We use Tasks, a very powerful feature of .NET 4.0. Each Task makes a call to the external service. Then we wait for all tasks to finish and return the data.
GetProduct method call takes about two seconds, life is good. What else to write about here?

The post is called "The Power of Async" but the above code doesn't use any async features. It works on .NET 4.0 and there is not much we can do to improve it (at least without losing its readability).

Now let's see how .NET 4.5 can make our life even better.

Let's create a new service method GetProduct2 by copying the existing method, make it async and change one line of code:

        public async Task<Product> GetProduct2(int id)
        {
            var p = new Product { Id = id };

            var nameTask = new Task(() => { p.Name = GetProductName(id); });
            var priceTask = new Task(() => { p.Price = GetProductPrice(id); });
            var categoryTask = new Task(() => { p.Category = GetProductCategory(id); });

            nameTask.Start();
            priceTask.Start();
            categoryTask.Start();

            await Task.WhenAll(nameTask, priceTask, categoryTask);            

            return p;
        }

The only difference with the first version of the method is that instead of "Task.WaitAll" we are using "await Task.WhenAll" (and we also marked the method as async). Now it's time to see what both methods look like in action. Let's try and send 100 request to our server at the same time and see how they perform. For that I have created a simple client program calls the service 100 times are waits for all of them to complete.

        static void Main(string[] args)
        {
            var totalCompleted = 0; // number of requests completed

            const int N = 100; // number of requests to send

            var tasks = new Task<Product>[N];

            var sw = new Stopwatch();

            sw.Start();

            for (int i = 0; i < N; i++)
            {                
                // we are using the -Async version of the method because we want to send all requests at once
                var productTask = new ProductServiceClient().GetProductAsync(i);                

                // when the request is completed (we have the response)
                productTask.ContinueWith(_ =>
                {
                    // increment the number of requests completed
                    Interlocked.Increment(ref totalCompleted);

                    // output the results
                    Console.WriteLine("Total: {0}; Completed for: {1}", totalCompleted, _.Result.Name);                    
                });

                tasks[i] = productTask;

                Console.WriteLine(i);
            }

            // when all tasks are completed output the elapsed time
            Task.WhenAll(tasks).ContinueWith(_ => Console.WriteLine("Completed! {0}", sw.Elapsed));

            Console.ReadLine();
        }

 Please note that even though we do use some async stuff in our client program, it has nothing to do with the server implementation. The same client features are available to us no matter what the service is written in, be it C#, Java or PHP.

Let's now run the client program, open Task Manager and see how many threads our WCF service creates:


In this series of runs I only measured maximum number of threads created in the iisexpress process.

Before running any of the test I always killed the iisexpress processes and started them again to exclude any side effects. While running the client program (it takes about 40 seconds to complete) I was looking at the number of threads in the Task Manager. The maximum value for the GetProduct method (which uses Task.WaitAll) was 121 threads.

Not bad. Now let's modify our client program to call the GetProduct2 (which uses "await Tasks.WhenAll") method:

var productTask = new ProductServiceClient().GetProduct2Async(i);

And the result is... 63 threads. Wow. That's a good improvement for two lines of code.
How is that possible? The short story is WaitAll blocks the current thread while we are waiting for the response from the external service. And this blocking makes ThreadPool create a new thread in order for the product service to continue working. But WhenAll doesn't block the current thread. Instead it asks it to do other work in the meantime (for example process another request).
This is a very short explanation and I will try to elaborate on it in the next post.

Okay, we have dropped the number of threads almost two times by using the new async feature of C# 5. Can we do even better than that? The answer is yes.

While our new code doesn't block threads when waiting for product tasks to complete, we still make calls to the external service in a synchronous manner which, as you may have already guessed, leads to the current thread being blocked.

How can we avoid this blocking? By using the new client API from .NET 4.5 for calling a web service (actually the same as we used in the client program).
Let's add three new methods to call the external service. And this time let's make them async:

        private async Task<string> GetProductCategoryAsync(int id)
        {
            return await new ExternalServiceClient().GetProductCategoryAsync(id);
        }

        private async Task<long> GetProductPriceAsync(int id)
        {
            return await new ExternalServiceClient().GetProductPriceAsync(id);
        }

        private async Task<string> GetProductNameAsync(int id)
        {
            return await new ExternalServiceClient().GetProductNameAsync(id);
        }

Again, these methods don't care about the external service implementation at all. It could be anything conforming to web service standards.

And finally let's add new version of the GetProduct method, GetProduct3 that calls these new async methods:

        public async Task<Product> GetProduct3(int id)
        {
            var p = new Product();

            var nameTask = GetProductNameAsync(id).ContinueWith(t => p.Name = t.Result);
            var priceTask = GetProductPriceAsync(id).ContinueWith(t => p.Price = t.Result);
            var categoryTask = GetProductCategoryAsync(id).ContinueWith(t => p.Category = t.Result);

            await Task.WhenAll(nameTask, priceTask, categoryTask);

            return p;
        }

Here we are using the ContinueWith method that accepts an Action that should be executed once the task completes. And of course it does that in a non-blocking way.

Let's change our client program to use GetProduct3 and run it... 54 threads. That's impresive.

Also, all client calls were completed after 21 seconds, which is twice as fast as the previous two versions.

After that I repeated all the tests for 1000 requests. Here is a summary table with the measures:

N = 100









Max # of ThreadsTotal Time
GetProduct (Task.WaitAll)12100:43
GetProduct2 (Task.WhenAll)6300:42
GetProduct3 (Task.WhenAll + Async service call)5400:21

N = 1000









Max # of ThreadsTotal Time
GetProduct (Task.WaitAll)13903:08
GetProduct2 (Task.WhenAll)8002:54
GetProduct3 (Task.WhenAll + Async service call)5301:27

 As we can see, using new async features helped us reduce the number of threads almost twice. And using the new API for calling web services improved the total processing time dramatically (which probably means the average request processing time has improved  greatly but to be completely sure I still have to do more detailed analysis).

In the next post I will try to use more advanced tools such as Performance Monitor to see what's happening under the hood. And explain the results by looking at how exactly the new async features work.

The code for this post is available here.

Monday, March 14, 2011

How to insert an image into an Excel document

Let's assume we want to insert an image into an existing Excel document specifying the following parameters:
  • Image file name
  • Row and column of a cell we want to insert it to
  • Maximum size for an image (in pixels) so that scaling is performed if needed
  • Image offset inside a cell (in pixels)
To do this we will use OpenXML SDK from Microsoft which can be easily obtained here. The first link includes a powerful tool for working with OpenXML documents but for now we only need the SDK libraries. So go to the second link (OpenXMLSDKv2.msi) and download the installer.

Here's the code that solves the problem. I'm not going to delve into details of how it works, you can easily find them following the msdn link above. In a few words we create a new Drawing if it's not already present in the sheet. Then we do resizing to make sure the image fits into the given maximum size. After that we create OneCellAnchor element which is a key element here that contains the image itself and the information about  where exactly it will be placed.

private static void InsertImage(WorksheetPart worksheetPart, string imageFileName, int colNumber, int rowNumber, int maxWidth, int maxHeight, int offsetX, int offsetY)
{            
    var drawingsPart = worksheetPart.DrawingsPart ?? worksheetPart.AddNewPart<DrawingsPart>();

    if (!worksheetPart.Worksheet.ChildElements.OfType<Drawing>().Any())
    {
        worksheetPart.Worksheet.Append(new Drawing { Id = worksheetPart.GetIdOfPart(drawingsPart) });
    }

    if (drawingsPart.WorksheetDrawing == null)
    {
        drawingsPart.WorksheetDrawing = new Xdr.WorksheetDrawing();
    }

    var worksheetDrawing = drawingsPart.WorksheetDrawing;

    var imagePart = drawingsPart.AddImagePart(ImagePartType.Jpeg);

    using (var stream = new FileStream(imageFileName, FileMode.Open))
    {
        imagePart.FeedData(stream);
    }

    var positioningEMU = new ImagePositioningEMU(imageFileName, maxWidth, maxHeight, offsetX, offsetY);

    var extentsCx = positioningEMU.Width;
    long extentsCy = positioningEMU.Height;

    if (extentsCy > positioningEMU.MaxHeight || extentsCx > positioningEMU.MaxWidth)
    {                
        var scaleX = (double)extentsCx / (double)positioningEMU.MaxWidth;
        var scaleY = (double)extentsCy / (double)positioningEMU.MaxHeight;
        var scale = Math.Max(scaleX, scaleY);
        extentsCx = (int)((double)extentsCx / scale);
        extentsCy = (int)((double)extentsCy / scale);
    }

    var colOffset = positioningEMU.OffsetX;
    var rowOffset = positioningEMU.OffsetY;

    var nvps = worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>();
    var nvpId = nvps.Count() > 0 ?
        (UInt32Value)worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>().Max(p => p.Id.Value) + 1 :
        1U;

    var oneCellAnchor = new Xdr.OneCellAnchor(
        new Xdr.FromMarker
        {
            ColumnId = new Xdr.ColumnId((colNumber - 1).ToString()),
            RowId = new Xdr.RowId((rowNumber - 1).ToString()),
            ColumnOffset = new Xdr.ColumnOffset(colOffset.ToString()),
            RowOffset = new Xdr.RowOffset(rowOffset.ToString())
        },
        new Xdr.Extent { Cx = extentsCx, Cy = extentsCy },
        new Xdr.Picture(
            new Xdr.NonVisualPictureProperties(
                new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = "Picture " + nvpId, Description = imageFileName },
                new Xdr.NonVisualPictureDrawingProperties(new A.PictureLocks { NoChangeAspect = true })
            ),
            new Xdr.BlipFill(
                new A.Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = A.BlipCompressionValues.Print },
                new A.Stretch(new A.FillRectangle())
            ),
            new Xdr.ShapeProperties(
                new A.Transform2D(
                    new A.Offset { X = 0, Y = 0 },
                    new A.Extents { Cx = extentsCx, Cy = extentsCy }
                ),
                new A.PresetGeometry { Preset = A.ShapeTypeValues.Rectangle }
            )
        ),
        new Xdr.ClientData()
    );

    worksheetDrawing.Append(oneCellAnchor);
}
There is one interesting moment though. You may have noticed using of a strange class ImagePositioningEMU. The reason we need it is Excel stores most of its positional data in EMU units. And we can't just use pixels for image size, we need to convert them to EMU.  This is a job of that helper class. It's very simple so I'm not putting it here but you can find it in the attached solution archive.

And finally this is how we call the method.

static void Main(string[] args)
{
    using (var document = SpreadsheetDocument.Open("Empty.xlsx", true))
    {                
        var worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(
            document.WorkbookPart.Workbook.Sheets.Elements().Single(s => s.Name == "Sheet1").Id.Value
        );

        InsertImage(worksheetPart, "lighthouse.jpg", 5, 10, 200, 200, 20, 10);
    }
}
Here we are inserting the picture at the 5th column and the 10th row. The dimensions of the inserted image must not exceed 200 pixels. And it must be inserted 20 pixels right and 10 pixels down from the top left corner of the cell.
If we open the resulting file we can see the following picture.











The full solution is available here.