Wednesday, March 24, 2010

Basics about Monitor in .NET

The Monitor class controls access to objects by granting a lock for an object to a single thread. Object locks provide the ability to restrict access to a block of code, commonly called a critical section. While a thread owns the lock for an object, no other thread can acquire that lock.

Psudo code for synchronizing access to critical section:
------------------------------------------
morCodeLock = new object();

Monitor.Enter(morCodeLock);

//ender critical section
try
{
//do some work
under condition1
Monitor.Wait(morCodeLock) // cannot continue, put to waiting queue
//do some work
under condition2
Monitor.Pulse(morCodeLock) //ready to run, put to ready queue
}
finally
{
Monitor.Exit(morCodeLock);
}
//leave critical section
-----------------------------------------------

The synchronization object "morCodeLock" maintains the following information:
1. A reference to the thread that currently holds the lock.
2. A reference to a ready queue, which contains the threads that are ready to obtain the lock.
3. A reference to a waiting queue, which contains the threads that are waiting for notification of a change in the state of the object morCodeLoc.

The Pulse, PulseAll, and Wait methods must be invoked from within a synchronized block of code. These methods plus ready and waiting queues allow Monitor to have more control over synchronized code section which can be useful in producer-consumer and other scenarios. The executing thread can decide when to put itself into waiting queue and moved other thread(s) from the waiting queue to the ready queue,

Monitor.Enter(morCodeLock):
The call will lock morCodeLock object if it is not locked and the calling thread enters the critical region, otherwise (morCodeLock is locked already) the calling thread will be put in the ready queue.

Monitor.Wait(morCodeLock):
The thread that currently owns the lock on the specified object invokes this method in order to release the object so that another thread can access it. The caller is blocked while waiting to reacquire the lock. This method is called when the caller needs to wait for a state change that will occur as a result of another thread's
operations. When a thread calls Wait, it releases the lock on the object and enters the object's waiting queue. The next thread in the object's ready queue (if there is one) acquires the lock and has exclusive use of the object. All threads that call Wait remain in the waiting queue until they receive a signal from Pulse or
PulseAll, sent by the owner of the lock. If Pulse is sent, only the thread at the head of the waiting queue is affected. If PulseAll is sent, all threads that are waiting for the object are affected. When the signal is received, one or more threads leave the waiting queue and enter the ready queue. A thread in the ready queue is permitted to reacquire the lock. This method returns when the calling thread reacquires the lock on the object. Note that this method blocks indefinitely if the holder of the lock does not call Pulse or PulseAll.

Monitor.Pulse(morCodeLock):
The thread that currently owns the lock on morCodeLock invokes this method to signal the next thread in line for the lock. Upon receiving the pulse, the waiting thread is moved to the ready queue. When the thread that invoked Pulse releases the lock, the next thread (the head) in the ready queue (which is not necessarily the thread that was pulsed) acquires the lock. To signal multiple threas, use the PulseAll method.

More details:
The Monitor class does not maintain state indicating that the Pulse method has been called. Thus, if you call Pulse when no threads are waiting, the next thread that calls Wait blocks as if Pulse had never been called. If two threads are using Pulse and Wait to interact, this could result in a deadlock. Contrast this with the behavior of the AutoResetEvent class: If you signal an AutoResetEvent by calling its Set method, and there are no threads waiting, the AutoResetEvent remains in a signaled state until a thread calls WaitOne, WaitAny, or WaitAll. The AutoResetEvent releases that thread and returns to the unsignaled state.

Monitor vs Waithandle:
It is important to note the distinction between use of Monitor and WaitHandle objects. Monitor objects are purely managed, fully portable, and might be more efficient in terms of operating-system resource requirements. WaitHandle objects represent operating-system waitable objects, are useful for synchronizing between managed and unmanaged code, and expose some advanced operating-system features like the ability to wait on many objects at once.

Code Sample:
-------------------------------------------
class TestMonitor
{
object morCodeLock = new object();

public void Test()
{
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(this.TestCriticalRegion, i);
}
}

void TestCriticalRegion(object o)
{
int i = (int)o;
Console.WriteLine("thread " + i.ToString() + " Enter method");

Monitor.Enter(morCodeLock);
try
{
if (i == 0)
Monitor.Wait(morCodeLock);
Console.WriteLine("thread " + i.ToString() + " start critical");
Thread.Sleep(5000);
Console.WriteLine("thread " + i.ToString() + " end critical");
if (i == 4)
Monitor.Pulse(morCodeLock);
}
finally
{
Monitor.Exit(morCodeLock);
}
Console.WriteLine("thread " + i.ToString() + " exist method");
}
}
-------------------------------------------
Output:
thread 0 Enter method
thread 1 Enter method
thread 1 start critical
thread 2 Enter method
thread 3 Enter method
thread 4 Enter method
thread 1 end critical
thread 1 exist method
thread 2 start critical
thread 2 end critical
thread 2 exist method
thread 3 start critical
thread 3 end critical
thread 4 start critical
thread 3 exist method
thread 4 end critical
thread 4 exist method
thread 0 start critical
thread 0 end critical
thread 0 exist method

Friday, March 19, 2010

Basics about WaitHandle in .NET

WaitHandle is an abstract class under System.Threading namespace. It provides internal works for other synchronization objects inherited from it (for example EventWaitHandle) to block the current thread using its WaitOne(), WaitAny(), WaitAll(), or SignalAndWait() methods. The synchronization objects provide their own implementations to send signal (calling Set() for example) to unblock the thread.

Psudo code action:
---------------------------------------------
static eventWaitHandle1 = new EventWaitHandle;

//call in thread1 to block thread1
eventWaitHandle1.WaitOne();

//Call in thread2 to send signal to unblock thread1
//thread2 needs to hold a reference to eventWaitHandle1
eventWaitHandle1.Set()
---------------------------------------------
Synchronization objects used in this way can have two states: signaled and unsignaled. When in unsignaled state and wait methods are called, calling thread(s) are blocked; When in signaled state, thread(s) blocked on it can pass through. The constructors can defined which state to start with.

There are 2 modes that affect what state (signaled or unsignaled) the object to be in after being signaled. They are defined by EventResetMode Enumeration: EventResetMode.AutoReset and EventResetMode.ManualReset. Synchronization objects' constructors can defined which mode to use.
EventResetMode.AutoReset:
When signaled, the EventWaitHandle resets automatically after releasing a single thread. If no threads are waiting, the EventWaitHandle remains signaled until a thread blocks, and resets after releasing the thread. AutoResetEvent class has this mode built-in.

EventResetMode.ManualReset:
When signaled, the EventWaitHandle releases all waiting threads and remains signaled until it is manually reset (by calling Reset method). ManualResetEvent class has this mode built-in

More details:
If the initial state of the event is nonsignaled, threads that wait on the event will block. If the initial state is signaled, and the ManualReset flag is specified for mode, threads that wait on the event will not block. If the initial state is signaled, and mode is AutoReset, the first thread that waits on the event will be released immediately, after which the event will reset, and subsequent threads will block.

Sample code:
---------------------------------------------
class WaitOneTest
{
static EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

public void Test()
{
Thread tr = new Thread(new ParameterizedThreadStart(this.WorkerProc));
tr.Start(ewh);

Console.WriteLine("working in Main");

//block current thread untill ewh get signaled
ewh.WaitOne();

Console.WriteLine("after waitone");

}  //put a breakpint here to see the action

public void WorkerProc(object obj)
{
Console.WriteLine("worker does some work");

//give some time to make clear the effect of signaling
Thread.Sleep(10000);

//send signal but this doesn't mean the blocked thread
//will start right away. The switch is up to the operating system.
((EventWaitHandle)obj).Set();

Console.WriteLine("after calling set");
}
}
---------------------------------------------

Wednesday, January 13, 2010

Encoding and File in .NET

  1. Contents can be stored in a file in various formats: ASCII, Unicode, BASE64, Binary or others.
  2. Unicode contents allows a optional byte order mark(BOM) to be placed at the beginning of the file to indicate the byte order and signal the unicode representation (utf8/utf16/utf32) of the content which can be used by a file consumer to detect the format.
  3. File contents can be represented in .NET program as text (string, char[]) or binary (byte[]). Different representations can be obtained using different IO classes. 
  4. StreamReader/StreamWriter classes are dealing with text contents. That means they need a way to transform text to and from stream. This is accomplished by the encoding object associated to the StreamReader/StreamWriter classe. The associated encoding object's constructor allows you to set if the BOM will be written to (StreamWriter) or auto detected (StreamReader) from the file. The unicode formate if detected will be used other than the one being associated.
  5. Byte array can be obtained from the file, for example, using File.ReadAllBytes. Then the GetString method of a encoding class can be used to convert it into text if you know the format used to store the file. You can use the GetBytes method of an encoding class to conver text content into encoded byte array.
  6. There are many ways to deal with files, but encoding almost always plays a role either behind the scene or used by your code explicitly.

Wednesday, January 6, 2010

.NET Framework Regular Expression Object Model

The Regular Expression Engine

The regular expression engine in the .NET Framework is represented by the Regex class. The class provides sets of instance and static methods to achieve similar purposes. Regex class will be discussed more later.

Regular Expression Object Model includes some important classes. The Match class inherits from Group class which in turn inherits from the Capture class. Therefore both Match and Group are captures but in different sense. Match.value (value is inherited from Capture) reflects the whole matched string, but Group.value reflects the captured string for the group. The Match.Groups[0] is a special group. It always exists and represents the entire matched stirng that equals to Match.value.Other groups may exist if grouping is defined in the pattern. Subsequent Group[>0].value will contain only string that matches the pattern defined for the group.A group has more than 1 capture only when it has a quantifier defined.

You can call the methods of the Regex class to perform the following operations:
  • Determine whether a string matches a regular expression pattern.
  • Extract a single match or the first match.
  • Extract all matches.
  • Replace a matched substring.
  • Split a single string into an array of strings.
Determine whether a string matches a regular expression pattern
Sample: Regex.IsMatch("abcabc abcabce", @"(abc){2}e?")
This returns true because there is at lease one match found in the input string.

Extract a single match or the first match
Sample: Match match = Regex.Match("abcabc abcabce", @"(abc){2}e?")
This returns the first match found in the input string. The match.value in the sample returns "abcabc". In this case, match.groups[0].value = "abcabc", and match.groups[1].value = "abc".

Extract all matches
Sample: MatchCollection matches = Regex.Matches("abcabc abcabce", @"(abc){2}e?")
This returns all matches found in the input string. The matches[0].value in the sample returns "abcabc" and matches[1].value in the sample returns "abcabce".


Replace a matched substring
Sample: Regex.Replace("abcabc abcabce", @"(abc){2}e?", @"$1xyz")
This returns the input string with the mathed substrings replaced by the replacement string which, in this case, is "abcxyz". The result is "abcxyz abcxyz".
You can also use Match.Result("replace string") to replace matched string in a single match. Regex.Match("abc", "(?<ab>ab)c").Result("${ab}de") will return "abde".

Split a single string into an array of strings
Sample: Regex.Matches("abcabc abcabce", @"[\w\s]").
This will return an array of matches consisting of 14 characters and essentially parsing the string into a character array.

Thursday, November 26, 2009

Use TraceSource and traceListeners in .NET 2.0

The first part contains the C# code that writes trace events to TextWriterTraceListener, ConsoleTraceListener and EventLogTraceListener. The second part does exactly the some thing but using configuration file to achieve it.
-----------
Part 1
-----------
//using System;
//using System.Diagnostics;
private static void TraceTest()
{
TraceSource ts = new TraceSource("TestConsole");
SourceSwitch sw = new SourceSwitch("testSwitch");
//the level determines what events are sent to listerners,
//currently events level of Information and up.
sw.Level = SourceLevels.Information;
ts.Switch = sw;

//Remove the default DefaultTraceListener
ts.Listeners.Clear();

TextWriterTraceListener twtl= new TextWriterTraceListener(@"testLog.log");
twtl.Name = "text";
//Events of Warning level or up are written to log file
EventTypeFilter etf1 = new EventTypeFilter(SourceLevels.Warning);
twtl.Filter = etf1;
ts.Listeners.Add(twtl);

// set false to write to standard output stream
ConsoleTraceListener ctl = new ConsoleTraceListener(false);
ctl.Name = "console";
//Events of Information level or up are written to console
EventTypeFilter etf2 = new EventTypeFilter(SourceLevels.Information);
ctl.Filter = etf2;
ts.Listeners.Add(ctl);

//An event log source should not be created and immediately used.
//There is a latency time to enable the source, it should be created
//prior to executing the application that uses the source.
//To create an event source in Windows Vista, Windows XP Professional,
//or Windows Server 2003, you must have administrative privileges.
//MySource is the source used in code to reference the new event log.
//MyNewLog is the name shown in the Event View
//Run the following line only once and set a break point after it to allow enough time to create the event log
EventLog.CreateEventSource("MySource", "MyNewLog");

EventLogTraceListener evetl = new EventLogTraceListener("MySource");
evetl.Name = "eventLog";
//Events of Error level or up are written to event log
EventTypeFilter etf3 = new EventTypeFilter(SourceLevels.Error);
evetl.Filter = etf3;
ts.Listeners.Add(evetl);
//TraceEventType used here is first filtered by sw.Level
//to determine if the trace event should be sent to a listener.
//The TraceEventType has to be at the sw.Level or up to be sent.
//When a listener receives the event, it outputs only those events
//to which the listener's filter(s) matches. If no filter is defined
//on the filter, the listener outputs all events that send to it.
ts.TraceEvent(TraceEventType.Error, 1, "error message");
ts.TraceEvent(TraceEventType.Warning, 2, "warning message");
ts.TraceEvent(TraceEventType.Information, 3, "information message");
ts.Flush();
ts.Close();
}

----------
Part 2
---------
//using System;
//using System.Diagnostics;
private static void TraceTest()
{
TraceSource ts = new TraceSource("TestConsole");

ts.TraceEvent(TraceEventType.Error, 1, "error message");
ts.TraceEvent(TraceEventType.Warning, 2, "warning message");
ts.TraceEvent(TraceEventType.Information, 3, "information message");

ts.Flush();
ts.Close();
}
---- Code above uses the configuration settings below ---
<system.diagnostics>
    <sharedListeners>
        <add name="text" type="System.Diagnostics.TextWriterTraceListener" initializeData="testLog.log">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning" />
        </add>
        <add name="console" type="System.Diagnostics.ConsoleTraceListener" >
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Information" />
        </add>
        <add name="eventLog" type="System.Diagnostics.EventLogTraceListener"          initializeData="MyNewLog">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
        </add>
    </sharedListeners>
    <sources>
        <source name="TestConsole" switchName="testSwitch" switchType="System.Diagnostics.SourceSwitch">
            <listeners>
                <add name="text" />
                <add name="console" />
                <add name="eventLog" />
                <remove name="Default"/>
            </listeners>
       </source>
    </sources>
    <switches>
           <add name="testSwitch" value="Information"/>
    </switches>
</system.diagnostics>

Thursday, November 19, 2009

Using fuslogvw.exe on Windows 2008

1. Set Registry key:
C:\mytemp>reg add HKLM\Software\Microsoft\Fusion /v EnableLog /t REG_DWORD /d 1
The operation completed successfully.

2. Right click Visual Studio 2008 command Prompt and select Run as Administrator to open command window.
C:\Program Files\Microsoft Visual Studio 9.0\VC>fuslogvw.exe will open the tool.

3. Keep all default settings. Click Settings click Log All Bindings to Disk then select Enable custom log path. Enter a valid folder path such as "c:\MyFusionLog" in the Custom log path textbox. Make sure the folder is empty. When it starts to work, you can change the log setting as you desired.

4. Give full access to "c:\MyFusionLog" folder for Administrator account which should be the account you are running under.

5. Run a .Net application then click Refresh button to view binding log entries. Clicking each entry will open browser based log views which are stored under "c:\MyFusionLog\default"

Wednesday, November 18, 2009

Assembly Binding - Probing

Search Steps :

Determine the right version by using publisher policy file and configuration files

Search Global assembly cache

<CodeBase> defined in policy file overwrite the one defined in configuration file below

<Configuration><Runtime><AssemblyBinding><DependentAssembly><CodeBase> defined in configuration file.The url could be location in the intranet or internet, but the referenced assemply must be strongly named. Otherwise (private assembly) the url must be relative to the application directory.

If culture is included, following folders are searched:
[application base] / [culture] / [assembly name].dll [application base] / [culture] / [assembly name] / [assembly name].dll

Without culture, following folders are searched:
[application base] / [assembly name].dll
[application base] / [assembly name] / [assembly name].dll

<Configuration><Runtime><AssemblyBinding><DependentAssembly><Probing>: semicolon seperated paths below application base defined by AppDomain.CurrentDomain.BaseDirectory. When defined, followng folders are searched:
If culture is included, the following directories are probed:
[application base] / [binpath] / [culture] / [assembly name].dll
[application base] / [binpath] / [culture] / [assembly name] / [assembly name].dll
If culture information is not included, the following directories are probed:
[application base] / [binpath] / [assembly name].dll
[application base] / [binpath] / [assembly name] / [assembly name].dll

If an assembly uses the LoadFrom method to reference another assembly, the calling assembly's location is considered to be a hint about where to find the referenced assembly (this would be in different loading context from above).

Saturday, November 14, 2009

Type.FindMembers Method Explained

Syntax

public virtual MemberInfo[] FindMembers
(
     MemberTypes memberType,
     BindingFlags bindingAttr,
     MemberFilter filter,
     Object filterCriteria
)
MemberTypes enum: type of members to be included such as Constructor, Field, Method;
BindingFlags enum (FlagAttributes=bitwise combination): Flags to define the scope of members to be   included. Must specify Instance or Static along with Public or NonPublic or no members will be returned.
MemberFilter delegate: Used to filter qualified members based on the filterCriteria.
public delegate bool MemberFilter
(
     MemberInfo m,
     Object filterCriteria
)
Each qualified member (passed as MemberInfo) is compared to filterCriteria and included in the output if the comparison returns true.
The filter can be obtained from: Type.FilterAttribute, Type.FilterName, Type.FilterNameIgnorCase.
TheFilterAttribute uses the fields of FieldAttributes, MethodAttributes, and MethodImplAttributes as search criteria, and the other two delegates use String objects as the search criteria
Object filterCriteria: Passed into MemberFilter as filterCriteria. Its value depends on the type of filter used as described above. This parameter is more powful when used with FilterName and FilterNameIgnorCase since it can take the wild card form like "*" or "fun*".

Example
public class c1
{
     private int privateF1;
     public static int publicF1=2;
     public void method1(){ }
     private void method12(){ }
     private void method2(){ }
}
MemberInfo[] mi =
typeof(c1).FindMembers(MemberTypes.Field, BindingFlags.Public |

BindingFlags.Static, Type.FilterAttribute, FieldAttributes.Public);

// mi includes a single memeber: publicF1

MemberInfo[] mi =
typeof(c1).FindMembers(MemberTypes.Method, BindingFlags.Public |

BindingFlags.NonPublic |
BindingFlags.Instance, Type.FilterName, "method1*");

//mi includes two members: method1 and method12

jw






Saturday, October 31, 2009

The need of DataLoadOptions

=======
Problem
=======
If you run the following C# code on Northwind database, there will be one query sent to db to get the Customers needed and also one seperate query for each customer to get the individual order count:
-------------------------
var query = from c in db.Customers
where c.CustomerID.StartsWith("A")
select c;

foreach (var c in query){ Console.WriteLine( c.ContactName + " " + c.Orders.Count);}
-------------------------
It can be a lot of queries if customers are large.
============================================================
Witout using DataLoadOptions, we can do the same using single query as below:
=======================================================
------------------------------
var query = from c in db.Customers
where c.CustomerID.StartsWith("A")
select new {name=c.ContactName, count=c.Orders.Count};

foreach (var c in query){ Console.WriteLine( c.name + " " + c.count);}
------------------------------
The above code makes difference because we added the query needed to get the count into the same query for getting Customer. LINQ to SQL is smart enough to parse it into a single query, which has the same effect as seting the DataLoadOptions.
=============================================
Using the following code, you can get Customers with all their Orders in one query just like by setting DataLoadOptions to Orders:
============================================
---------------------------------------
var query = from c in db.Customers
where c.CustomerID.StartsWith("A")
select new {name=c.ContactName, count=c.Orders};
--------------------------------------
Then you can access related Orders collection in you code by looping through the anonimous objects generated.

Saturday, October 3, 2009

Power of SQL indexing

I run a SQL script on a server with 8 CPUs. The script took exceptionally long when updating two ntext fields in a table that has more than 3,000,000 records.
Before adding a nonclustered index:
The server showed 100% cpu committed and updated about 20,000 rows/hr
After adding a nonclusterd index:
The server updated 15,000 rows/min(not hr!).
I was shocked by such a big improvement.

Sunday, May 24, 2009

Domain name resolution in Windows

These are the major steps for name resolution. If at any step the requested name is resolved, the result will be returned and the steps below it will not be taken:

Try to resolve on the client first:



  1. Use preloaded local host file.

  2. Use local DNS cache.

If fail to resolve on the client, try resolve the name on the server by sending a DNS request:



  1. Use the prefered DNS server address configured for the current network connection. If failed to connect to the prefered DNS server, use other DNS server in the order listed in the Advanced TCP/IP Settings / DNS under "DNS server addresses, in order of use" box.

  2. The selected server tries to resolve using configured zone info.


Friday, April 3, 2009

My First Post

I think the site provides me a nice place to keep some useful stuff in one place, specially those learned from my development experience.