5 December 2011

Handling System Shutdown / Logoff events in C#.NET

On .NET forums, I often come across people interested in knowing about notifications of something changed in the system. For example whether windows is shutting down, whether user is logging off, power mode changed, or system font changed etc. For instance, you may want to perform some operation when your application is terminating. In that case, what are all the possible ways of terminating the application?
  1. Closing the application by clicking close 'x' button
  2. Due to exception
  3. User kills the process
  4. When the user logs off or system shuts down
The first 2 are common scenarios which the user can take care of easily. But what about the 3rd and 4th cases? The 3rd case is, I don't think we can control. However, 4th one is interesting. When the system shutdown is started either by user or by any automated process, the shutdown process will terminate all running processes. Before that it sends a signal to all running processes that the system is going to shutdown. Upon receiving this signal, a process can do any windup operation so as to prevent any data loss. This is very important because you might be in middle of some important operation and sudden application termination may cause valuable data loss.

So, how do a .NET application receives this signal? Whenver it comes to the matter of system related things, many people think of native OS DLLs or PInvoke (some unmanaged way). But wait, we have some managed objects that do the work. There is a class called SystemEvents in Microsoft.Win32 dll which offers many system based events. You can google or refer MSDN for more info SystemEvents class. Here, I will just take an example of how System shutdown or user logoff events are handled.

Below is a simple console application that displays a message box whenever a system shutdown occurs or user logs off (In any case, it causes CLR to unload and hence a notification is sent about the event).

class Program
{
    static void Main(string[] args)
    {
        SystemEvents.SessionEnding += SystemEvents_SessionEnding;
        Console.ReadLine();  //This is needed to keep the application running.
    }

    static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
    {
        switch (e.Reason)
        {
            case SessionEndReasons.Logoff:
                MessageBox.Show("User logging off");
                break;

            case SessionEndReasons.SystemShutdown:
                MessageBox.Show("System is shutting down");
                break;
        }
    }
}

Beware of excessive string objects

Of all the primitive types in C#, string is a special primitive type in the following regard,

  1. It is a reference type (class), unlike - other primitive types being ValueType.
  2. It is immutable - i.e. once a string is created, it's contents cannot be altered.

Since string is a reference type, a string object must be created on a managed heap which should be garbage collected when the object becomes orphan. This is fine in the sense that at one or other place we can't avoid creating managed objects and all managed objects have to be garbage collected. But, if you look at the second point above which states strings are immutable. Having said this, what if you want to manipulate the string contents (like appending substring, converting to lower case etc.) ? Ofcourse you can do that. But, the original string is never altered, instead, a new string object is created with new value. What does that mean? Take a look at below code.


    string s1 = "Hello World";
    string temp = s1;           // store the reference of s1 into temp
    s1 = "New World";           // modify s1.
 

First I created a string s1 with value "Hello Word". Then I stored the reference of s1 in temp i.e. both temp & s1 are pointing to the same object. You can verify that by calling Object.ReferenceEquals (s1, temp) which will return true if the reference is same. Then I modify s1 to "New World". At this time, I am actually creating a new String rather than modifying the value in s1. You can verify that by comparing contents of temp and s1. So what is the impact of this? Well, to know the impact, see the below code.
 

    string s = string.Empty;
    Stopwatch watch = new Stopwatch();
    Int32 count = 0;
       
    watch.Start();
    while (true)
    {
        s = s + (count++).ToString();

        if (watch.ElapsedMilliseconds >= 1000)
        {
            break;
        }
        //Thread.Sleep (1);
    }
 
When I ran this code on my i3 machine running Windows7, the loop ran approximately 3 million times. Also, Garbage collection (Gen0) ran for 100 times !!! This is really huge impact on the performance. This is because, after every loop, a new string is created and the old reference becomes the candidate for garbage collection. Also, if you look at the average size of string created at every loop - it is 3Mb. If the garbage collection had not occured, just calculate the total memory occupied by all strings in one second. Thanks to GC for avoiding a disaster. When I uncommented the Sleep statement, the GC collection count reduced to 0.1 per second as the number of strings created per second reduced from 3 million to just 300 ! 
 

Above demo clearly states that too many strings in memory is not good. So, what are all the possible ways?

  1. Prefer StringBuilder over String in cases involving heavy string manipulations
  2. Avoid string manipulations inside a loop at all possible places.
  3. Avoid too many class level/ global string fileds.
 

22 November 2011

Be Careful of Constant fields in .NET

We all know that Constant fields are those whose value never changes in the lifetime of an application. Constant are really useful constructs that offer many benifits to the user like,
  • Constants make developer sure that their value never changes (even by mistake).
  • Constants are compile time values, which means their values are directly embedded inside the metadata. Hence, constants don't require memory allocation at runtime.
All that said, there is a risk in using the constants if appropriate care is not taken. See the second point above - "constant values are embedded directly inside the metadata". This statement has an impact when you have constant fields in a DLL which are used in one or more applications. Let me start demostrating you through a sample code. Consider that the below class exists in a library called MyLibrary.DLL.


public class GlobalConstants
{
    public const Int32 MAX_VALUE = 2;
    public const String MALESTRING = "Male";
    public const String FEMALESTRING = "Female";
}


Now, I have to use GlobalConstants in my application. For that I will create a Console Application called SampleClient.exe. Inside the Main function I use the above constants as


class Program
{
    static void Main(string[] args)
    {
        int maxValue = GlobalConstants.MAX_VALUE;
        String Female = GlobalConstants.FEMALESTRING;

        Console.WriteLine(maxValue);
        Console.WriteLine(Female);
    }
}


Build SampleClient.exe and run it directly from bin folder. Your application will print 2  and Female as expected and everything is fine. Now I got a requirment that MAX_VALUE should be changed to 100, MALE should be "Man" and FEMALE should change to "Woman". Ok, thats fine. I will update GlobalConstants in MyLibrary.DLL class as below.


public class GlobalConstants
{
    public const Int32 MAX_VALUE = 100;
    public const String MALESTRING = "Man";
    public const String FEMALESTRING = "Woman";
}


I will re-build MyLibrary.DLL and send the dll for use in SampleClient.exe. So, place the new dll in bin folder of SampleClient and run it. SampleClient is now refering to new MyLibrary.DLL. But what output do you see? you expect that it will print 100 and Woman but it still prints 2 and Female. So, what is the problem? For that you need to see the IL code of Main method in SampleClient.



Observe that the values 2 and FEMALE are hardcoded in the IL. Though you have changed MAX_VALUE to 100 & FEMALE to "Woman", the values are not reflected. To correct this problem, you must re-build SampleClient application too to make use of new constant value in the dll. Rebuilding SampleClient will embed the new MAX_VALUE and FEMALE values into metadata of Main method.

With this problem, consider your DLL is consumed by Hundreds of applications. So, changing a constant value in your library will result in rebuilding of all it's consumers. So, be careful with constants, use them only when you are sure that their value never-ever change or if they change, you afford re-building it's consumers. Or, if you think constant values may change, then prefer using 'readonly' fields over constants. I will discuss about 'readonly' fields in my next writing.

15 November 2011

Creating Multi Column ComboBox in .NET

Recently I was working on an assignment wherein I had to create a Custom ComboBox to display multiple columns when it is dropped down. Something similar to below image.




The actual assignmet was little more complex than the one I have shown in the above image. Anyways, if you look at the image, you will also find the combo box pretty useful as it can display data in column manner like FirstName-LastName, Name-Place etc. So, if you like it, you can design it yourself. All you have to do is, create class that inherits ComboBox, set the DrawMode property to OwnerDrawFixed, override OnDrawItem method to draw the columns manually.

Sounds simple, isn't it? Now, how do we supply items to this ComboBox? If we have to display an item in multicolumn fashion, ideally the item must be composite one i.e. a Dictionary<T, T> or a class with 2 instance members. Since ComboBox's Items property is a collection of objects, we can place anything into it. This has got both advantage as well as disadvantages.   Advantage is we can place object of our custom class into ComboBox while the disadvantage is user can enter any kind of item which cannot be represented in the way we need to display it.

Ok, all that said, I will create a class whose instances we are going to place in the combo box. I will call this class as XComboItem (X stands for Extended).


public class XComboItem
{
    public String DisplayName { get; set; }
    public Object Value { get; set; }
    public String Description { get; set; }
}


So, this is the class, whose objects we are going to place in out custom combo Box. I will name the combo as XComboBox.


public partial class XComboBox : ComboBox
{
    private Int32 ColumnGap = 20;
    private Int32 firstColumnWidth;
    private Int32 secondColumnWidth;
    public XComboBox(): base()
    {
        DrawMode = DrawMode.OwnerDrawFixed;
        firstColumnWidth = DropDownWidth / 2;
        secondColumnWidth = DropDownWidth / 2;
    }
}


In this, firstColumnWidth and secondColumnWidth are the widths of both columns that I am going to display in combo dropdown list (in pixels). Column gap is gap between two columns.Initially I will set the column widths to half the width of DropDownWidth. The only major thing is to override OnDrawItem() function. By overriding this function, you can draw the items in DropDownList of the combobox in the way you want. You can display each item with different font, differen style or even add image to each item. In our case, we need to display DisplayItem & Description of XComboItem in two seperate columns. The logic is getting the drawing object of current item, then use DrawString method appropriately. So, here goes our OnDrawItem.

protected override void OnDrawItem(DrawItemEventArgs e)
{
    if (e.Index < 0)
    {
        return;
    }

    XComboItem item = (XComboItem)Items[e.Index];
    ColumnGap = firstColumnWidth == 0 ? 0 : ColumnGap;
    e.DrawBackground();
    e.DrawFocusRectangle();
    String first = item.DisplayName;
    String second = item.Description;

    while (TextRenderer.MeasureText(first, e.Font).Width > firstColumnWidth)
    {
        first = first.Substring(0, first.Length - 1);
    }

    Brush solidBrush = new SolidBrush(e.ForeColor);
    e.Graphics.DrawString(first, e.Font, solidBrush, e.Bounds.Left, e.Bounds.Top);
    e.Graphics.DrawString(second, e.Font, solidBrush, e.Bounds.Left + firstColumnWidth +
                          ColumnGap, e.Bounds.Top);
}


You can add any properties or methods to make the control more user friendly. So, That's it, our control is ready. To use, create the object of XComboItem and add the object to Items collection of XComboBox. Then run your application to see the effect.

4 September 2011

Built-in General Purpose Delegates in .NET

In day-to-day coding, we often need to create delegates. Every time we need a delegate, we usually create a new delegate and use it. But, if you know .NET already provides some ready made delegates which we can use for varying purposes. So, in this post I will be discussing some of the common built-in delegates that we can use for general purpose.

System.Action: The Action delegate can accept any method which takes zero arguments and returns void. The declaration goes like

public delegate void Action();
System.Action<…> : This is a generic version of System.Action delegate. This delegate can accept any method that takes 1 to 16 parameters and returns void. You can use this delegate as below,

public void SomeMethod(int a, string b, double c){}
System.Action<int, string , double> action = new System.Action<int, string , double>( SomeMethod );

System.Comparison<T>: Actually this delegate is used for specific purpose, I am discussing this here because it is often used in Sorting techniques.  This takes a method as parameter which takes two arguments of type T and return an Integer. For example, I want to sort list of employees based on their first names then I can do it as,

private int CompareEmpoyees(Employee a, Employee b)
{
     return a.FirstName.CompareTo(b.FirstName);
}

ListempList = GetEmployeeList();
Comparison comparer = new Comparison(CompareEmpoyees);
empList.Sort(comparer);


System.Func<…, out TOut> : This is a generic delegate that accepts any method that takes 0 to 16 arguments of any type and return an argument of type TOut. For example,

public Employee SomeMethod(int a, string b, double c)
{
}

System.Action<int, string , double> action = new System.Action<int, string , double, Employee>( SomeMethod );

System.MethodInvoker: This delegate is similar to System.Action delegate which accepts a method that takes zero arguments and returns void. But, as the name suggests, this delegate is used at places where you need to talk to UI elements from a background thread. Something like below,

MethodInvoker mi = new MethodInvoker ( () => { textBox1.Text = "Hello World"; });
this.Invoke(mi);


That is it for now. I will be editing this page if I find any other delegates that fit here. Meanwhile, If you want me to add anything here, please let me know.