PDB and ClickOnce
Bit of history first. PDB – Program Debug Database is essential sometimes during debugging. By default, stack trace points to the function where problem lies and don’t include line numbers at which errors are thrown. Sometime this becomes quite critical for a serious production issue. Best practice seems to build PDBs during your build process (both Debug / Release), exclude them while creating your installers, and ship them to production when you need to diagnose your code. Another related thing you might want to keep in mind while debugging some critical issue – you can create a debug build by turning off code optimization (project properties -> Build Tab -> Optimize Code (uncheck)). This helps you to get an accurate stack trace devoid of any code optimizations like inline functions. Let’s get back to PDBs, the topic of this post. Enabling PDB effect normally is done by turning them on (Project Properties -> Build -> Advanced -> Debug Info = pdb-only) and copying generated PDBs to deployment directory. But when you are using ClickOnce things are different. In ClickOnce, the assemblies are downloaded the client’s local machine and then executed (deriving the benefit of auto update). So how do you ensure that the client download PDBs with assemblies? Fortunately VS.NET simplifies this for us. Steps are below:
1) Go the publish tab of your project file and click on “Application Files” button.
2) By default PDB files are not bundled for publish. You need to check “Show All Files” check box and then you would get to see PDB. PDB again is excluded by default, so include them. And you are all set to get line numbers and file names with your stack trace.
Hope this helps
.
.NET Worker Threads, I/O Threads And Asynchronous Programming
Before I talk about Asynchronous programming, I will outline type of threads available in .NET environment. CLR maintains a pool of threads (to amortize thread’s creation cost) and it should be the place to look for when you need to create more threads. Thread pool maintains 2 types of threads – Worker & I/O. As name implies Worker threads are computational threads while I/O are used for wait (block) of long duration (e.g. when invoking a remote WCF service). A good rule to follow is to ensure your all waits are on I/O thread, provided they are long enough otherwise you would end up degrading your performance due to a context switch. Let’s understand what above statement means with a bit of code. Your entry point to CLR’s thread pool is ThreadPool class. Code below helps you find how many threads are there in thread pool
int wt, iot;
ThreadPool.GetAvailableThreads(out wt, out iot);
Console.WriteLine(“Worker = ” + wt);
Console.WriteLine(“I/O = ” + iot);
One can only request for a worker thread by ThreadPool.QueueUserWorkItem. If all worker threads are occupied your request will be blocked till time a worker thread is available. Below sample shows how you can consume & monitor worker threads.
int wt, iot;
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(Dummy);
}
Console.ReadLine();
ThreadPool.GetAvailableThreads(out wt, out iot);
Console.WriteLine("Worker = " + wt);
Console.WriteLine("I/O = " + iot);
static void Dummy(object o)
{
Thread.Sleep(50000000);
}
Unlike worker threads you don’t have any direct API to request for I/O threads. But .NET leverages I/O threads automatically when we use asynchronous programming. Below code uses asynchronous operations on client side to invoke a WCF Service
for (int i = 0; i < 10; i++)
{
/* Invoke a WCF Service via a proxy, asynchronously*/
client.BeginGetData(10, null, null); /*Put some Thread.Sleep in server side code*/
}
ThreadPool.GetAvailableThreads(out wt, out iot);
Console.WriteLine("Worker = " + wt);
Console.WriteLine("I/O = " + iot);
Contradictory to expectations of many, the output of the above program shows that only one I/O thread is in use instead of 10. This optimization makes I/O so important and something you should care about. As a good designer of your application you want to ensure that minimal threads are blocked and I/O threads just give you that. Also note when call returns another I/O thread is picked up from pool and callback method gets executed, hence we should avoid touching UI from callback method.
So why should one use Asynchronous programming? There are quite a few reasons but what I also see is many programmers miss on server side asynchronous programming & focus just on client aspect of it. Also irrespective of whether you are doing client or server side I strongly recommend you set timeouts for your I/O operations (WCF defaults this to 60 seconds).
Client Side:
1) You don’t want to block UI while processing the request with server (though I have found that this creates other issues like handling UI parts that are only to be activated post request, accessing UI from callback thread, exception handling, etc.)
2) You want to issue simultaneous requests to your server so that all of them are processed in parallel and your effective wait time is the wait time of longest request (though in case you are making requests to same server you can try the DTO pattern to create a chunky request & break the request up on server for parallel processing)
3) You just want to queue up a request (message queue)
Server Side:
1) Normally there is throttle placed on server side handling. If you sever side code is I/O oriented (Calling long processing DB query / remote web service) you are better off doing that on an asynchronous thread. For more information you can refer to ASP.NET link and WCF link.
I haven’t mentioned about asynchronous ADO.NET in this post and you can find more information about it here.
So what are your scenarios for using asynchronous programming?
Loading 2 Versions of the same .NET Assembly
This can be an interview question
. Let’s say I have a class
public class Class1 //1.0.0.0 – in C:
{
public string SayHello()
{
return “Hello World”;
}
}
and I version it to 2.0.0.0
public class Class1 // in C:\2 folder
{
public string SayHello()
{
return “Hello India”;
}
}
So you have 2 assemblies. Now, write a program in .NET to print Hello World & Hello India. Simple – use Assembly.LoadFrom (LoadFrom takes a path while Load goes through Assembly Resolver & Loader).
class Program
{
static void Main(string[] args)
{
Assembly assm = Assembly.LoadFrom(@”C:\ClassLibrary1.dll”);
Type[] types = assm.GetTypes();
foreach (var t in types)
{
Object obj = assm.CreateInstance(t.FullName);
Console.WriteLine(t.GetMethod(“SayHello”).Invoke(obj, null));
}
Assembly assm2 = Assembly.LoadFrom(@”C:\2\ClassLibrary1.dll”);
Type[] types2 = assm2.GetTypes();
foreach (var t in types2)
{
Object obj = assm2.CreateInstance(t.FullName);
Console.WriteLine(t.GetMethod(“SayHello”).Invoke(obj, null));
}
}
}
But to your suprise the output remains – “Hello World” & “Hello World”. If you take the second block first, output will change to “Hello India” & “Hello India”. Neither of them is what we expected. Conclusion – It’s not possible to load 2 assemblies by same name inside a single AppDomain. So you will have to create a seperate AppDomain & load the second version of assembly into it as shown below:
class Program
{
static void Main(string[] args)
{
Assembly assm = Assembly.LoadFrom(@”C:\ClassLibrary1.dll”);
Type[] types = assm.GetTypes();
foreach (var t in types)
{
Object obj = assm.CreateInstance(t.FullName);
Console.WriteLine(t.GetMethod(“SayHello”).Invoke(obj, null));
}
AppDomain app = AppDomain.CreateDomain(“Child”, AppDomain.CurrentDomain.Evidence, new AppDomainSetup { ApplicationBase = @”C:\2″ });
Assembly assm2 = app.Load(@”ClassLibrary1″);
Type[] types2 = assm2.GetTypes();
foreach (var t in types2)
{
Object obj = assm2.CreateInstance(t.FullName);
Console.WriteLine(t.GetMethod(“SayHello”).Invoke(obj, null));
}
}
}
Do you have any better ways?
Logging Best Practices
These are couple of good links I came across on logging best practices – One & Two. I have been using Log4Net for all my projects though Logging Application Block from Enterprise Library seems to be equally good. There is a full fledged war out there between two, but I normally don’t see a major motivation to move to latter. Log4Net has got many trace levels which you can flip through your config file – FATAL, ERROR, DEBUG, WARN & INFO. They start from most limited logging to maximum.
Normally I see myself using ERROR & DEBUG only most the time as it’s hard to communicate with developers when they have to draw line between others. My minimum instructions (though not enough, see post script at end of this post) are
1) Use ERROR LEVEL for all exceptions & ensure that hook into unhandled execptions
2) Use DEBUG level to note entry & exit of each method (some people also prefer to log each input to the method as well). This one needs to be more contextual with revlevant information to your domain as simple entry/exit you can retrive from exception’s stack trace as well. Some people use this to find performance bottlenecks in their system during production.
I will briefly elaborate steps to get started with Log4Net for above:
1) Add reference to log4net.dll into your project (This is required per project).
2) Modify your config file to add a log4net configsection & specify various appenders. This config is the for the main projects not class library projects. E.g. you have Presentation (ASP.NET) & Data Access Layer (C# Class Library) only web.config of your presentation project should be altered.
<?xml version=”1.0″ encoding=”utf-8″?>
<configuration>
<configSections>
<!–This is a must addition–>
<section name=”log4net” type=”log4net.Config.Log4NetConfigurationSectionHandler,log4net” />
</configSections>
<log4net>
<appender name=”RollingFileAppender” type=”log4net.Appender.RollingFileAppender,log4net”>
<param name=”File” value=”C:\\HRESWeb.log” /><!–File where the log should reside–>
<param name=”AppendToFile” value=”true” />
<!– FOR DATE BASED ROLL BACKUP –>
<param name=”rollingStyle” value=”Date” />
<param name=”datePattern” value=”yyyyMMdd” />
<layout type=”log4net.Layout.PatternLayout,log4net”>
<!–Pattern to add timestamp, type, etc.–>
<param name=”ConversionPattern” value=”%d [%t] %-5p %c [%x] – %m%n” />
</layout>
</appender>
<root>
<level value=”ERROR” /> <!–Just change the level to DEBUG for informative logging–>
<appender-ref ref=”RollingFileAppender” />
</root>
</log4net>
</configuration>
3) Add an entry in the AssemblyInfo.cs of the project whose config you edited in the second step.
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "ConsoleApplication7.exe.config")]
or for Web.config
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config")]
4) Start logging
Normally you would create a static ILog Object per class by specifying the class type as parameter & then use Debug & Error Methods for Logging
static readonly ILog log = LogManager.GetLogger(typeof(Program));
log.Debug(“Debug Message”);
// No need to check if Debug level is enabled. Log4Net does that internally
log.Error(“Error Message”);
// A sample method with minimum features
public void SomeMethod()
{
try
{
log.Debug(“Entering”); // Add your contextual information here e.g. patient you processing, claim you working
//… Do Something
log.Debug(“Exiting”); // Contextual information here as well
}
catch (Exception ex)
{
log.Error(“Description : “, ex);
throw; //Don’t forget this
}
}
Logging is also normally implemented via AOP (I had posted a similar article using Unity on CodeProject, though this one deals with transactions).
Also I would recommend that exceptions are also posted in the Windows Event Logs (you can create a category for your application), the motivation being that this increases visibility & is easy for admins to locate them instead of wading through your text, Udi organizes the same thought here.
P.S. An effective way to find out how good your logging is, ask developers to debug without breakpoints during development. If they can do it just by looking at log file, you are on your way, else you might have to get ready for post production nightmares.

