Sunday, January 27, 2008

Override ToString()

.Net IDE provides excellent support for debugging. One of the supporting tools is the Watch window. It does a very good job when it comes to displaying of data, but it doesn't always display the data in the best form, especially for the classes that we write. But that is not the fault of the Watch window, its we the developers who are not providing correct implementation of ToString() to our classes.

The .net debugger calls the ToString() automatically on the instance which is to be monitored in the watch window. If we override the ToString() implementation in our class and provide the key fields as part of implementation, that will make our job a lot easier when it comes to debugging.

See the following code listing. Run it with the ToString() method commented and add a instance of the clsExample class nin watch window and notice the data. Compare it with the original verison.


using System.Diagnostics;

namespace DebuggererAttribute

{

public class clsExample

{

private int _FieldOne;

private double _FieldTwo;

private string _FieldThree;

private bool _FieldFour;

public int FieldOne

{

get

{

return _FieldOne;

}

set

{

_FieldOne = value;

}

}

public double FieldTwo

{

get

{

return _FieldTwo;

}

set

{

_FieldTwo = value;

}

}

public string FieldThree

{

get

{

return _FieldThree;

}

set

{

_FieldThree = value;

}

}

public bool FieldFour

{

get

{

return _FieldFour;

}

set

{

_FieldFour = value;

}

}

public override string ToString()

{

return string.Format("FieldOne = {0}, FieldTwo = {1}, FieldThree = {2}, FieldFour = {3}", _FieldOne, _FieldTwo, _FieldThree, _FieldFour);

}

public clsExample()

{

_FieldOne = 2;

_FieldTwo = 3.66;

_FieldThree = "This is some text";

_FieldFour = true;

}

}

}

Sunday, January 20, 2008

AutoResetEvent Object and Hanged Application

This is something related to a bug which was not so reproduce able , but was seen once a week at least on one of the many test machines. We used to get a "Server busy" dialog box and Switching or Retrying did not do anything. We have to kill the application.

I was accustom to see this dialog when a COM server is busy or is waiting for some resource and usually after some time, Switching or Retrying worked.

Fortunately i got this error on my development machine once and more fortunately i was running a debug build. I paused the program and watched the call stack. The program was waiting on a thread which was in a "Wait or Sleep/Join state". Drilling down more on the thread, it was found that it was one of the our own application thread.

This information gave me a good deal of information on where to look for. I checked the module which created the thread and found that it was created in a user control and the thread was using a AutoResetEvent object. The wait state of the thread as i discovered earlier from call stack was from the Dispose call of the user control. I checked the code to see the places where the AutoResetEvent was closed or signaled. Well the object was not cleaned up/closed in the Dispose call "which was the problem".

The thread was waiting on the AutoResetEvent object and was not allowing the user control to Dispose and hence the application to close.

Learning:
1. Clean up all variables manually, don't rely on GC. GC does a good job, but we screw up our selves thinking GC will take care.
2. Use of thread and windows kernel objects like Mutex, Semaphores etc (thread synch objects) are a double edged sword. Always use them with caution.

Saturday, January 5, 2008

How much a Thread cost you?

I was recently wondering if creating n number of threads will affect the memory usage of an application. I created a sample application which created a thread on a button click to observe the memory usage on each thread creation. The thread proc as such did nothing; I had put a sleep statement in it so that the thread is alive and is using the memory for some time while I am creating some more threads.

I was relaxed to see that the memory usage in task manager rose by just 20K -30 K on each thread creation with an exception that the first thread creation increased the memory by around 1 MB.


Later I started checking Virtual memory usage as well and was shocked to see 1 MB of memory usage on each thread creation! A little goggling revealed that by default each thread is assigned a 1 MB stack! Check out the sample code which prints out the Virtual Memory usage of the test application in debug window on each thread creation.

//code
private static void Somethread()
{
Debug.WriteLine(string.Format("Started thread with thread id {0}", Thread.CurrentThread.ManagedThreadId));
//Print task managers VM Size column
Debug.WriteLine(string.Format("Current VM usage is {0} MB", (Process.GetCurrentProcess().PagedMemorySize64 / (1024 * 1024))));

Thread.Sleep(1000 * 60 * 1); // let the thread live for some time while we create some more threads
Debug.WriteLine(string.Format("----Ended thread with thread id {0}", Thread.CurrentThread.ManagedThreadId));

//Print task managers VM Size column
Debug.WriteLine(string.Format("Current VM usage is {0} MB", (Process.GetCurrentProcess().PagedMemorySize64 / (1024 * 1024))));

}

private void btnCreateThread_Click(object sender, EventArgs e)
{
//Each created thread will be allocated 1 MB of Virtual memory
Thread samplethread = new Thread(Somethread);
samplethread.IsBackground = true;
samplethread.Start();
}

Conclusion: Want to keep a small footprint of the application, think twice before creating a new thread.

How do I clear the ARP cache?

The Microsoft Windows ARP cache will occasionally become corrupt and need to be cleared.

The first symptom you are likely to notice is that connections to web pages will time out and fail.

If you troubleshoot further, you will notice that you can `ping` your IP address and also 127.0.0.1, but not other IP addresses.

Clearing the ARP Cache

To fix this error, you will need to clear the ARP cache. This is done with the `netsh` command:

C:\>netsh interface ip delete arpcache
Ok.

Viewing the ARP Cache

If you would like to view your ARP cache, this can be accomplished using the `arp` command:

C:\>arp -a

Interface: 192.168.1.100 --- 0x10004
Internet Address Physical Address Type
192.168.1.1 00-0f-66-37-22-32 dynamic

If Clearing the ARP Cache Fails

Occasionally, clearing your ARP cache will fail due to a bug in Microsoft Windows.

If you try to use Microsoft Windows to repair the network connection, you will receive an error message that says:

Windows could not finish repairing the problem because the following operation could not be completed:
Clearing the ARP cache
For assistance, contact the person who manages your network

This bug occurs when Routing and Remote Services is enabled. Routing and Remote Services is almost unnnecessary and can be turned off unless you know that you are using it.

To disable Routing and Remote Services:

  • Click the button
  • Click the button
  • Switch to "Classic View" if you are in "Category View"
  • Click
  • Click
  • Double-click
  • Double-click
  • Scroll down to
  • Double-click
  • Examine the "Startup Type"
  • The options are "Automatic", "Manual", and "Disabled"
  • Set the "Startup Type" to "Disabled"
  • Examine the "Service status"
  • Make sure that the service status is Stopped. If it is not Stopped, click the button
  • Click the button

Now, try clearing the ARP cache again and it should complete with no error messages.


Extracted from http://www.tech-faq.com/clear-arp-cache.shtml

Readonly Vs Const

1. Const are faster than readonly.
2. Const are not binary compatible if the same const is used in different assemblies.
3. Const can only be used with primitive data types, which can be initialized while declaration.
4. Const are available at compile time and readonly at runtime.
5. Const should be preferred only for values that does not change between releases.
6. Const can be preferred if they are accessible only within an assembly.

Properties

1. Provides encapsulation, enabling code maintainability and bug fixing.
2. Data binding classes in .net supports properties but not variables.
3. Adding multi-threaded support is much easier.
4. Can be extended in interfaces.
5. One of the accessors can be have a different visibility.
6. Supports of parameterized properties (indexers).
7. Changing public data members to Properties at a later stage will break binary compatibility. So it’s better to start right.

Friday, January 4, 2008

Tip: Find those errors quickly

Every programmer out there learns or is told to write exception handlers in their code, and yes it’s necessary. But many write try{} catch{} just for the sake writing error handlers with no error logging in catch{}. Now this works in opposite direction, instead of working as an error logging tool, the application just suppress errors.

If there is a null object reference error in code, neither even the programmer nor the QA ever knows it, unless the error affects the output of the program. Even if the output of the program is not affected, exceptions are costly and must be handled with care.

Here is a neat trick to catch those errors which are suppressed in empty catch blocks in development environment.

Just set the “Thrown” Common Language Runtime Exceptions check box as shown in the image.


This will make sure that the program breaks on any exception that is thrown.


Breaking the program on each and every exception is sometime nagging. To turn off break on all exception, one can un-check specific exception type. This comes very handy when say one wants to suppress SocketExceptions.

Happy coding.