Loading blog entries.. loading


Blogs which referenced tag: [C#]

 

Modify proxy settings using Powershell

 
Written by Wayne Ye  Thursday, December 8, 2011

To use Live Messenger in the office, I always need to firstly disable my proxy settings, after Live Messenger launched, I need turn it back. Thus everytime I need to change that from "Internet Options -> Connections -> Lan Settings ->", check/uncheck the checkboxes, well, this task I need to do at least one time a day, I as a developer should achieve this in a more efficient and convenient way.

By overcoming one problem I wrote a snippet of Powershell cmdlet which does the job perfectly, the steps are:

  1. Update proxy settings to "Automatically detect settings".
  2. Launch Live Messenger.
  3. Update proxy settings to use proxy.

 The "one problem" I encountered and mentioned above is:

Where are the registry key(s) to store "Automatical configuration" section in Lan Settings.

I firstly tried to use Process Monitor by applying filter to only monitor my IE's process PID, while I did see it updated a number of places (see result outputed by procmon below), some of them are easy to be recognized such as "ProxyEnable", "ProxyOverride", etc, while I didn't see a obvious palce to store "Automatically detect settings".

 4:54:31.9881707 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\DefaultConnectionSettings    SUCCESS    Type: REG_BINARY, Length: 385, Data: 46 00 00 00 3D 00 00 00 09 00 00 00 15 00 00 00
4:54:31.9883681 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:31.9884340 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer    SUCCESS    Type: REG_SZ, Length: 44, Data: proxy.aus.hp.com:8080
4:54:31.9884568 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride    SUCCESS    Type: REG_SZ, Length: 60, Data: dummyA.com;dummyB.com;<local>
4:54:31.9886357 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\SavedLegacySettings    SUCCESS    Type: REG_BINARY, Length: 385, Data: 46 00 00 00 B5 02 00 00 09 00 00 00 15 00 00 00
4:54:31.9899406 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:31.9899612 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer    SUCCESS    Type: REG_SZ, Length: 44, Data: proxy.aus.hp.com:8080
4:54:31.9899892 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride    SUCCESS    Type: REG_SZ, Length: 60, Data: dummyA.com;dummyB.com;<local>
4:54:31.9901306 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\SavedLegacySettings    SUCCESS    Type: REG_BINARY, Length: 385, Data: 46 00 00 00 B6 02 00 00 09 00 00 00 15 00 00 00
4:54:32.0357094 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad\{65249C59-E027-4F0B-83FF-27DBB0B4E19E}_{B9E1413C-BF8C-444E-8FD0-105D9DD10F49}\WpadDecisionReason    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:32.0358754 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad\{65249C59-E027-4F0B-83FF-27DBB0B4E19E}_{B9E1413C-BF8C-444E-8FD0-105D9DD10F49}\WpadDecisionTime    SUCCESS    Type: REG_BINARY, Length: 8, Data: 60 20 7E 00 87 B5 CC 01
4:54:32.0360316 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad\{65249C59-E027-4F0B-83FF-27DBB0B4E19E}_{B9E1413C-BF8C-444E-8FD0-105D9DD10F49}\WpadDecision    SUCCESS    Type: REG_DWORD, Length: 4, Data: 1
4:54:32.0362007 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad\{65249C59-E027-4F0B-83FF-27DBB0B4E19E}_{B9E1413C-BF8C-444E-8FD0-105D9DD10F49}\WpadNetworkName    SUCCESS    Type: REG_SZ, Length: 24, Data: cpqcorp.net
4:54:32.5961530 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\EnableAutodial    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:32.5961684 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\NoNetAutodial    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:32.5969457 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:32.5969722 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer    SUCCESS    Type: REG_SZ, Length: 44, Data: proxy.aus.hp.com:8080
4:54:32.5969907 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride    SUCCESS    Type: REG_SZ, Length: 60, Data: dummyA.com;dummyB.com;<local>
4:54:32.5971154 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\SavedLegacySettings    SUCCESS    Type: REG_BINARY, Length: 385, Data: 46 00 00 00 B7 02 00 00 09 00 00 00 15 00 00 00
4:54:32.9694553 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\DefaultConnectionSettings    SUCCESS    Type: REG_BINARY, Length: 641, Data: 46 00 00 00 3E 00 00 00 09 00 00 00 15 00 00 00
4:54:32.9696389 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Wpad\WpadLastNetwork    SUCCESS    Type: REG_SZ, Length: 156, Data: {65249C59-E027-4F0B-83FF-27DBB0B4E19E}_{B9E1413C-BF8C-444E-8FD0-105D9DD10F49}
4:54:39.7267907 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable    SUCCESS    Type: REG_DWORD, Length: 4, Data: 0
4:54:39.7268135 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer    SUCCESS    Type: REG_SZ, Length: 44, Data: proxy.aus.hp.com:8080
4:54:39.7268366 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyOverride    SUCCESS    Type: REG_SZ, Length: 60, Data: dummyA.com;dummyB.com;<local>
4:54:39.7270232 PM    iexplore.exe    2992    RegSetValue    HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\SavedLegacySettings    SUCCESS    Type: REG_BINARY, Length: 641, Data: 46 00 00 00 BE 02 00 00 09 00 00 00 15 00 00 00

By a short time googling I found the answer on the awesome StackOverFlow, the "Automatical configuration" setting is stored in:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\DefaultConnectionSettings

And the tricky part is, it is a Reg_Binary value, and the 9th binary number indicates the value of the two checkboxes, that is:

01 - neither of those 2 auto config boxes are checked

05 - just the Use automatic configuration script is checked

09 - just the Automatically detect settings is checked

0d - both of them are checked

 By knowing this I am ready to write my Cmdlet code, I pasted below:

 # 1.Modify proxy settings to "Automatically detect settings". i.e. Disable proxy
CD HKCU:\"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
Set-Itemproperty . DefaultConnectionSettings -Value ([byte[]](0x46,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x70,0x72,0x6F,0x78,0x79,0x2E,0x61,0x75,0x73,0x2E,0x68,0x70,0x2E,0x63,0x6F,0x6D,0x3A,0x38,0x30,0x38,0x30,0x1D,0x00,0x00,0x00,0x64,0x75,0x6D,0x6D,0x79,0x41,0x2E,0x63,0x6F,0x6D,0x3B,0x64,0x75,0x6D,0x6D,0x79,0x42,0x2E,0x63,0x6F,0x6D,0x3B,0x3C,0x6C,0x6F,0x63,0x61,0x6C,0x3E,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x61,0x75,0x74,0x6F,0x63,0x61,0x63,0x68,0x65,0x2E,0x68,0x70,0x2E,0x63,0x6F,0x6D,0xA0,0x9D,0xC6,0x4C,0x6B,0xB5,0xCC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x02,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00))

CD HKCU:\"Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-ItemProperty . ProxyEnable 0

# 2.Launch Live Messenger
Start-Process "C:\Program Files (x86)\Windows Live\Messenger\msnmsgr.exe"

# 3.Sleep 10 seconds to allow live messenger signed in
Start-Sleep -s 10

# 4.Restore proxy back
CD HKCU:\"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
Set-Itemproperty . DefaultConnectionSettings -Value ([byte[]](0x46,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x70,0x72,0x6F,0x78,0x79,0x2E,0x61,0x75,0x73,0x2E,0x68,0x70,0x2E,0x63,0x6F,0x6D,0x3A,0x38,0x30,0x38,0x30,0x1D,0x00,0x00,0x00,0x64,0x75,0x6D,0x6D,0x79,0x41,0x2E,0x63,0x6F,0x6D,0x3B,0x64,0x75,0x6D,0x6D,0x79,0x42,0x2E,0x63,0x6F,0x6D,0x3B,0x3C,0x6C,0x6F,0x63,0x61,0x6C,0x3E,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x61,0x75,0x74,0x6F,0x63,0x61,0x63,0x68,0x65,0x2E,0x68,0x70,0x2E,0x63,0x6F,0x6D,0xA0,0x9D,0xC6,0x4C,0x6B,0xB5,0xCC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x02,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x10,0xBB,0x56,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00))

CD HKCU:\"Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-ItemProperty . ProxyEnable 1

C:
Echo Finished
Exit

Well, I put the sccript file on my desktop and named "Launch Live Messenger.ps1", every time I can simplt right click on it and select "Run with Powershell".


View Post»



Permalink:http://wayneye.com/Blog/Modify-Proxy-Settings-Using-Powershell
Tag:

Atomic Operation in C#.Net

 
Written by Wayne Ye  Tuesday, October 25, 2011

Introduction

Atomic Operation is named academic to Linearizability, Atomicity is a guarantee of isolation from concurrent processes, it can be enfored by hardware level build on Cache Coherence protocol, or software level exclusive lock. In this blog post, I am going to explore a few number of mechanisms to achieve atomic operation in .Net.

What are Atomic operations and what are not?

In C# Specification, the stamement about atomic operation is:

“Reads and writes of the following data types shall be atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.” Also: “…there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.”.

Threading In C# by Joseph Albahari described:

"Read/write on a field of 32-bit or less is always atomic, operations on 64-bit are guaranteed to be atomic only in 64-bit OS, statements that combine more than one read/write operation are never atomic."

For example, following operations are guaranteed to be atomic operations:

 int i = 3; // Always atomic
long l = Int64.MaxValue; // Atomic in 64-bit enviroment, non-atomic on 32-bit environment

Code like below are never atomic:

 int i = 0;
int j += i// Non-atomic, read and write operation
i++;         // Non-atomic, read and write operation

And I am trying to document atomic operation in a lower level in the section below.

Essence

Comsidering two threads (or two processes) are running simultaneously: T1 and T2, there is a field stored in memory, T1 reads its value and do some calculation on the value and finally write the new value back to memory, during the period T2 was actually doing exact same task - i.e. read/calculate/write value back, so possibly one operation on this field overrides another - in other word: the later executed thread (T2) might override the earlier executed one (T1) because when it read the field's value another thread was just manipulating on it, and after T1 finished writing the new value back to memory, T2 writes back.

So a simple example is the increament/decrement operation, as I showed above, it is NOT an atomic operation, it requires both read and write, if many thread simultaneously doing increment on one field, it will very possible cause race condition (the more threads, the more increment operation going to do, the more possibility race condition happen).

Atomicity example

I wrote a Winform application, it do simple work:

Create 10 threads at runtime and simultaneously operates on a private interger, there is a volatile counter with initial value 0, every thread finishes its work will:

  1. Print information on UI.
  2. Increment the counter
  3. Check whether the counter reachs 10, if yes, print CalculatingFinished method which will print the final result.

And I wish UI won't block during the calculation, otherwise I can simply join every created thread. My code skeleton is showing below:

 private const int MaxThraedCount = 10;
private Thread[] m_Workers = new Thread[MaxThraedCount];
private volatile int m_Counter = 0;
private Int32 x = 0;

protected void btn_DoWork_Click(object sender, EventArgs e)
{
    ShowStatus("Starting...");

    for (int i = 0; i < MaxThraedCount; i++)
    {
        m_Workers[i] = new Thread(IncreaseNumber) { Name = "Thread " + (i + 1) };
        m_Workers[i].Start();
    }
}

void IncreaseNumber()
{
    try
    {
        for (int i = 0; i < 10000; i++)
        {
            // Different strategy to increment x
        }

        ShowStatus(String.Format("{0} finished at {1}", Thread.CurrentThread.Name, m_Watcher.Elapsed.TotalMilliseconds));
       
        // Increases Counter and decides whether or not sets the finish signal
        m_Counter++;
        if (m_Counter == MaxThraedCount)
        {
            // Print finish information on UI
            CalculatingFinished();
            m_Counter = 0;
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

public void ShowStatus(string info)
{
    this.InvokeAction(() => listInfo.Items.Add(info));
}

private void CalculatingFinished()
{
    ShowStatus("\r\nAll Done at: " + m_Watcher.Elapsed.TotalMilliseconds);
    ShowStatus("The result: " + x.ToString());
}

I highlighted "// Different strategy to increment x", and will try a few number of ways to achieve atomicity using FCL libriries.

Let's first see the non-atomic routine - simple do x++ in each thread: 

 for (int i = 0; i < 10000; i++)
{
    x++;
}

Since x++ is NOT atomicity, in additional, I made a large loop - 10 thousand times, in my experience, I NEVER get the correct result, the screenshot is below:

Non-Atomic Operation

Analysis and solutions

To solve the issue and ensure atomicity, by more than 2 weeks brokenly study I found the following feasible ways (in theory, not considering performance):

  1. Interlocked.Increment
  2. Apply exclusive lock (or Moniter.Enter) outside the for loop.
  3. AutoResetEvent to ensure threads doing task one by one. 
  4. Create a temp integer in each thread and once finish add temp onto x under an exclusive lock.
  5. ReaderWriterLockSlim.
  6. Parallel.For coordinate with Interlocked.Increment. 

All of above can achieve atomic operation on incresing x's value, and got expected result:

Atomic operation

In fact I did try other ways such as using MemoryBarrier, Thread.VolatileRead/VolatileWrite - StackOverFlow question link, but failed, if dear readers know there is way to use them to achieve the goal please kindly guide me.  

Demonstration code

In this section I will listed key code for implementing the 5 solutions above.

Solution #1: Interlocked.Increment

 for (int i = 0; i < 10000; i++)
    Interlocked.Increment(ref x);

Solution #2: Apply exclusive lock (Moniter) outside the for loop.

 private readonly string m_Locker = "THREAD_LOCKER";

Monitor.Enter(m_Locker);
for (int i = 0; i < 10000; i++)
    x++;
Monitor.Exit(m_Locker);

Solution #3: AutoResetEvent to ensure threads doing task one by one.

 private static AutoResetEvent m_AutoReset = new AutoResetEvent(false);

protected void btn_DoWork_Click(object sender, EventArgs e)
{
    ShowStatus("Starting...");

    for (int i = 0; i < MaxThraedCount; i++)
    {
        m_Workers[i] = new Thread(IncreaseNumber) { Name = "Thread " + (i + 1) };
        m_Workers[i].Start();
    }
   
    m_AutoReset.Set();
}

void IncreaseNumber()
{
    m_AutoReset.WaitOne();
    for (int i = 0; i < 10000; i++)
        x++;
    m_AutoReset.Set();
}

One notable point is in this case (UI non-blocking) it is not easy to use Monitor.Enter/Monitor.Pulse pair to replace AutoResetEvent and implement "one by one" logic becasue Monitor.Pulse won't maitain state, below is the description in MSDN:

Important

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 WaitOneWaitAny, or WaitAll. The AutoResetEvent releases that thread and returns to the unsignaled state.


In my Winform application, if I call Monitor.Pulse() in button click event, many threads will not receive the signal (whereas AutoResetEvent will remain signaled state)! I wrote a simple routine to demonstrate this:
 private static readonly string _locker = "THREAD_LOCKER";
public static void Main()
{
    for(int i = 0;i<5;i++)
    {
        Thread t = new Thread(DoWork);
        t.Name = "T" + (i + 1);
        t.IsBackground = true;
        t.Start();
    }
   
    //Thread.Sleep(500);
   
    Monitor.Enter(_locker);
    Console.WriteLine("Main thread");
    Monitor.Pulse(_locker);
    Monitor.Exit(_locker);
}

private static void DoWork()
{
    Monitor.Enter(_locker);
    Monitor.Wait(_locker);
    Monitor.Pulse(_locker);
    Monitor.Exit(_locker);
    Console.WriteLine(Thread.CurrentThread.Name + " finished and exist");
}
Removing "Thread.Sleep(500)" will *VERY POSSIBLY* lead less than 5 thread working, because creating 5 threads requires not short time (kenel object, TEB, kenel/user stack), during the period one just created thread (T2) might get the signal or might not (much more possible), because when the previously created thread (T1) calling "Monitor.Pulse(_locker)" T2 had NOT been setup, T2 and the thread created later will have no chance to get signal! They will be waiting... So the 0.5 seconds is used to give time to create 5 thread, otherwise main thread will quit immediately and background thread will be collected.

Solution #4: Create a temp integer in each thread and once finish add temp onto x under a exclusive lock.

 private readonly string m_Locker = "THREAD_LOCKER";

void IncreaseNumber(object objThreadName)
{
    int tmp = 0;
    for (int i = 0; i < 10000; i++)
        tmp++;

    lock (m_Locker)
        x += tmp;
}

Solution #5: ReaderWriterLockSlim.

 void IncreaseNumber(object objThreadName)
{
    // Or we can use ReaderWriterLock.AcquireWriterLock(500) but it has more performance overhead and is not recommended
    m_ReaderWriterLocker.EnterWriteLock();
    for (int i = 0; i < 10000; i++)
        x++;
    m_ReaderWriterLocker.ExitWriteLock();  // Or ReaderWriterLock.ReleaseWriterLock();
}

Please note that ReaderWriterLock class is not recommended, it "take about five times longer to execute than a call to Monitor's Enter method." please refer: Reader/Writer Locks and the ResourceLock Library by Jeffery Richter.

Solution #6: Parallel.Forcoordinate with Interlocked.Increment.

 Parallel.For(0, 100000, (i) => Interlocked.Increment(ref x));

Conclusion

In this post I took a simple & straight-forward example: 10 threads simultaneously operating on on field, to experiment atomicity operation in C#.Net, using synchronization technology including exclusive locking, signaling, non-blocking synchronization, I guess this is a very good example to master basic FCL thread libraries/concepts such as Interlocked, Monitor, MemoryBarrier, volatile, AutoResetEvent, ReaderWriterLockSlim, etc.

Multi-threading programming is indeed very complex, during my investigation I happened to saw even Jon Skeet admitted he had “his eyes opened to the precise meaning of volatile which isn't "always read from main memory, always write directly to main memory" (link), so as a rookie in this field I should invest more effort on it:)

Further Reading

Threading In C# (Strongly recommended!!!)

Linearizability Wikipedia

Introducing the new ReaderWriterLockSlim in Orcas

Asynchronous Code Blocks

Atomic Operations

Boosting Performance with Atomic Operations in .NET 4


View Post»



Permalink:http://wayneye.com/Blog/Atomic-Operation-In-Csharp
Tag:

Exception handling particulars in C#

 
Written by Wayne Ye  Friday, July 8, 2011

Background

Exception handling appears in most .NET applications, this post is trying to describe some  Exception handling particulars in C# which might not take enough awareness from C# developers. 

Differences between throw and throw ex 

I guess every C# developer has seen code snippet below:

 try
{
    // Do some work, exception occurs
}
catch (IOException ex)
{
    // Exception caught, re-throw it to bubble up
    throw ex;
}

In the catch block, we can rethrow the caught exception instance of IOException to higher level, and we may also saw another way in a little different:

 try
{
    // Do some work, exception occurs
}
catch (IOException ex)
{
    // Exception caught, re-throw it to bubble up
    throw;
}

Is there any different? 

The answer is yes! To prove that I wrote a simple snippet of code below, first is a simple customized Exception: DummyException.

 internal class DummyException : Exception
{
    public DummyException(String dummymsg)
        : base(dummymsg)
    {

    }

    public DummyException(String dummymsg, Exception innerException)
        : base(dummymsg, innerException)
    {

    }
}

 And then I manually throw the DummyException within one method, while handle it in different way mentioned above:

 class Program
{
    private static void DoLowLevelOperation()
    {
        // Do some low level operation
        throw new DummyException("A dummy exception message!");
    }

    public static void MethodThrowException1()
    {
        try
        {
            DoLowLevelOperation();
        }
        catch (DummyException de)
        {
            throw;
        }
    }
    public static void MethodThrowException2()
    {
        try
        {
            DoLowLevelOperation();
        }
        catch (DummyException de)
        {
            throw de;
        }
    }

    static void Main(string[] args)
    {
        try
        {
            MethodThrowException1();
        }
        catch (DummyException de1)
        {
            Console.WriteLine(de1.Message);
            Console.WriteLine(de1.StackTrace);
        }

        try
        {
            MethodThrowException2();
        }
        catch (DummyException de2)
        {
            Console.WriteLine(de2.Message);
            Console.WriteLine(de2.StackTrace);
        }
    }
}

 The result will be:


View Post»



Permalink:http://wayneye.com/Blog/Exception-Handling-Particulars-In-Csharp
Tag:

HTML5 Web Socket in Essence

 
Written by Wayne Ye  Friday, June 10, 2011

HTML5 WebSocket defines a bi-directional, full-duplex communication channel operates through a single TCP connection, this article discusses its fantastic performance, the WebSocket protocol principle and its handshake mechanism, and develop a WebSocket application in action (Team Poker).


Embeded youku video link because Youtube is outside of the largest "intranet" in the entire universe!!

Table of Content

  1. Introduction
  2. Background
  3. WebSocket In Essence
  4. Experimental Demos
  5. Browser Support
  6. WebSocket JavaScript API
  7. Develop WebSocket In Action - Team Poker
  8. Open Issues
  9. Conclusion
  10. References & Resources 

Introduction

HTML5 WebSocket defines a bi-directional, full-duplex communication channel that operates through a single TCP socket over the Web, it provides efficient, low-latency and low cost connection between web client and server, based on WebSocket, developers can build scalablereal-time web applications in the future. Section below is the official definition of WebSocket copied from IETF WebSocket protocol page: 

The WebSocket protocol enables two-way communication between a user agent running untrusted code running in a controlled environment to a remote host that has opted-in to communications from that code.  The security model used for this is the Origin-based security model commonly used by Web browsers.  The protocol consists of an initial handshake followed by basic message framing, layered over TCP.  The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g. using XMLHttpRequest or <iframe>s and long polling).

This article is trying to go through WebSocket basic concept, the problems it is going to solve, explain it in essence, watch some experimental Demos, develop a simple WebSocket application in action (Team Poker), and describe current open issues of WebSocket. I sincerely hope it will be systematicallyeasy to understandfrom surface to deep so that eventually readers would not only learn what WebSocket is from high level but also understand it in depth! Any thoughts, suggestions or criticism you may have after reading this article will help me to improve in the future, i would appreciate it if you could leave a comment.

Background

In traditional web applications, in order to achieve some real-time interaction with server, developers had to employ several tricky ways such as Ajax pollingComet (A.K.A Ajax push, Full Duplex Ajax, HTTP Streaming, etc.), those technologies either periodically fire HTTP requests to server or hold the HTTP connection with server for a long time, which "contain lots of additional, unnecessary header data and introduce latency" and resulted in "an outrageously high price tag". websocket.org explained the problems exhaustively, compared the performance of Ajax polling and WebSocket in detail, built up two simple web pages, one periodically communicated with server using traditional HTTP and the other used HTML5 WebSocket, in the testing each HTTP request/response header is approximate 871 byte, while data length of WebSocket connection is much shorter: 2 bytes after connection established, as the transfer count getting larger, the result will be:

Traditional HTTP Request 

  • Use case A: 1,000 clients polling every second: Network throughput is (871 x 1,000) = 871,000 bytes = 6,968,000 bits per second (6.6 Mbps)

  • Use case B: 10,000 clients polling every second: Network throughput is (871 x 10,000) = 8,710,000 bytes = 69,680,000 bits per second (66 Mbps)

  • Use case C: 100,000 clients polling every 1 second: Network throughput is (871 x 100,000) = 87,100,000 bytes = 696,800,000 bits per second (665 Mbps)

HTML5 WebSocket

  • Use case A: 1,000 clients receive 1 message per second: Network throughput is (2 x 1,000) = 2,000 bytes = 16,000 bits per second (0.015 Mbps)

  • Use case B: 10,000 clients receive 1 message per second: Network throughput is (2 x 10,000) = 20,000 bytes = 160,000 bits per second (0.153 Kbps)

  • Use case C: 100,000 clients receive 1 message per second: Network throughput is (2 x 100,000) = 200,000 bytes = 1,600,000 bits per second (1.526 Kbps)

Finally a more readable diagram:

Polling VS WebSocket

 "HTML5 Web Sockets can provide a 500:1 or — depending on the size of the HTTP headers — even a 1000:1 reduction in unnecessary HTTP header traffic and 3:1 reduction in latency".  --WebSocket.org

WebSocket In Essence

The motivation of creating WebSocket is to replace polling and long polling(Comet), and endow HTML5 web application the ability of real-time communication. Browser based web application can fire WebSocket connection request through JavaScript API, and then transfer data with server over only one TCP connection.


View Post»



Permalink:http://wayneye.com/Blog/HTML5-Web-Socket-In-Essence
Tag:

Utilize gzip compression in IIS

 
Written by Wayne Ye  Friday, December 10, 2010

GZIP format is developed by GNU Project and standardized by IETF in RFC 1952, which MUST be considered by web developers to improve their websites' performance, there are several Quintessential articles documented using gzip compression, they are:


10 Tips for Writing High-Performance Web Applications
Best Practices for Speeding Up Your Web Site
How To Optimize Your Site With GZIP Compression
IIS 7 Compression. Good? Bad? How much?

A gzip compressed HTTP package can significantly save bandwidth thus speed up browser rendering after use hitting enter, so that user experience got improved finally, nowadays most of the popular browsers such as IE, Firefox, Chrome, Opera support gzip encoded content (please refer: http://en.wikipedia.org/wiki/HTTP_compression).

PS: the other compression encoding is deflate, "but it's less effective and less popular" (refer: http://developer.yahoo.com/performance/rules.html). Yahoo uses gzip compression and suggest developers do that:

 

Compression in IIS

For ASP.NET developer who host website


View Post»



Permalink:http://wayneye.com/Blog/IIS-Gzip-Compression
Tag:

A complete Impersonation Demo in C#.NET

 
Written by Wayne Ye  Friday, October 22, 2010

Under some scenarios we need impersonate another Windows account and do some work under that user’s session, for example:

  • An enterprise ASP.NET web application provides server administrators’ ability to access the server under some specific privilege set; Server admin input their NT account information (domain\account + password) on the page, we need get WinNT Access Token and then impersonate this server user, so that we acquire its specific privilege and do the things ONLY THIS ACCOUNT CAN DO.
  • We developed a Windows Service which needs internet access periodically, but a specific user sets an Sock5 proxy to access internet, then your Windows Service needs to know the Socks proxy information so that it could access internet, you must impersonate this user and read the settings.

Impersonation definition

Definition copied from: http://msdn.microsoft.com/en-us/library/aa376391(VS.85).aspx

Impersonation is the ability of a thread to execute using different security information than the process that owns the thread. Typically, a thread in a server application impersonates a client. This allows the server thread to act on behalf of that client to access objects on the server or validate access to the client’s own objects.

I read many articles and blogs and wrote an ImpersonateHelper class to do impersonation work, during the investigating I noticed that very few articles/blogs refer a complete impersonation process, so I decided to write one that refer as more details as I can, and actually my code was a code snippet combination came from 10+ sourcesSmile.

Functionality

I create a local user: TempUser which belongs to “Administrators” (make sure log on TempUser at least once), I logged on as my own account and I am going to impersonate TempUser and do two things:


View Post»



Permalink:http://wayneye.com/Blog/DotNet-Impersonation-Demo
Tag:

Encrypt .Net Configuration file

 
Written by Wayne Ye  Friday, June 11, 2010

Under some scenarios the developers want to encrypt some sections inside app.config or web.config file, this article How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA describes how to do so clearly, Scott Guthrie also posted one: Encrypting Web.Config Values in ASP.NET 2.0.

However, in the posts above they uses aspnet_regiis.exe and seems it doesn’t directly support app.config, if we want to encrypt app.config for Windows Form or WPF applications, while I tried use it to encrypt my app.config file, it generates a web.config which means my Winform definitely can’t use it, even if I copy the encrypted appSettings section from this generated web.config to my own app.config(ConfigurationManager.AppSettings[EncryptedKeyName] is null after I did that).

Config Encrypt


View Post»



Permalink:http://wayneye.com/Blog/Encrypt-DotNet-Configuration-File
Tag:

Personal Schedule Management Tool

 
Written by Wayne Ye  Wednesday, May 19, 2010

Time is always ticking no matter you care it or you don’t care it, everyone knows it including myself, to remind myself don’t waste too much time on gaming, reading news or something else, I developed a little tool which I call it “Personal Schedule Management Tool” to achieve this simple goal.

Mechanism

I create an XML file to store a serial of [time stamp/task to do] pairs, the tool will start with Windows and load the XML file, a working timer behind it will periodically check whether there is a task needs to be done at defined time stamp, once the condition is matched, the tool will

  1. Shows Windows Balloon Tips with the task as content, screenshot below.
    Balloon
  2. Invokes managed Microsoft Speech API: SpeechSynthesizer.Speak() to remind me even if I am not in front of my dev-box at that time.

Here is my XML to store schedule items:

<?xml version="1.0" encoding="utf-8" ?>
<WayneScheduleItems>
  <ScheduleItem TriggerHour="18" TriggerMinute="20" Content="Wayne, time to have your dinner." />
  <ScheduleItem TriggerHour="19" TriggerMinute="0" Content="Wayne! It is time to learn technologies and programming skills, i.e. CODING TIME!" />
  <ScheduleItem TriggerHour="20" TriggerMinute="30" Content="OK, your eye and brain need rest, time to do some body execise - running, sit-ups, push-up, etc.  Enjoy:)" />
  <ScheduleItem TriggerHour="21" TriggerMinute="0" Content="Well, sweat off your face and have a bath:)." />
  <ScheduleItem TriggerHour="21" TriggerMinute="30" Content="All right, well come back, you know you should read some books!" />
  <ScheduleItem TriggerHour="23" TriggerMinute="0" Content="Wayne, thanks for the hard work! Time to sleep, have a good night!" />
</WayneScheduleItems>


View Post»



Permalink:http://wayneye.com/Blog/Personal-Schedule-Management-Tool
Tag:

A good lesson and experience

 
Written by Wayne Ye  Thursday, September 3, 2009

I was extremely busy during the last two weeks, since our project was at bug fixing phase, my team and I worked really hard on dealing with the bugs; We fixed two to three bugs everyday by average, I am very satisfied with the efficiency myself.

During this process, I encountered several very interesting issues.

  1. There was a crash bug with P1 priority, we all cannot reproduced it until one guy from US team provided a remote server that our product always crashed, after I logged onto that server and 20 minutes investigating, I was really surprised, the reason is one line of code written by myself, it is:

    DateTime.Parse(String.Format("{0}/{1}/{2} 00:00:00 AM", DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Year))

    Does this line of code has any problem, I definitely don’t think so before, but now, I understand, it only works under English format, once non-English format, under some format such as Chinese, the AM makes non sense; and… Under some formats (such as French), the code will throw FormatException and leads program crash…

  2. Another issue is a WPF related multi-threading issue, there is a module in our product used thread pool to invoke WMI APIs to


View Post»



Permalink:http://wayneye.com/Blog/A-Good-Lesson-On-DateTime-Localization
Tag:

作息时间自动提醒Windows Service

 
Written by Wayne Ye  Friday, April 24, 2009

经济危机真真切切的影响到了几乎每一个人,09年过去三分之一多一点了,生活不太规律,确实太忙的说,工作换了,房子也换了,又做回了张江男,觉得自己再不好好努力会Out的。。。都奔三儿而去了。。。于是乎,为了勉励自己,做了这么个东东。

WSNSVC

一个Windows Service,里面跑一个Timer,每隔10秒check一下当前时间,一旦发现时间吻合,则调用Microsoft Speech Technology? 发声提醒,超级简单,不过。。。以后要么得一直戴着心爱的森海塞尔,要么只能用音箱了。。。

服务描述:
Notify Wayne to follow the schedule established by himself. If this service is disabled, Wayne may waste a lot of time...

项目层级:
SolutionHierarchy 

  • WayneScheduleService.cs Windows Service后台代码


View Post»



Permalink:http://wayneye.com/Blog/Personal-Schedule-Windows-Service
Tag:

这几天研究Url Rewrite:)

 
Written by Wayne Ye  Friday, March 21, 2008

在开发这个自己用的Blog时,决定认真研究一下以前接触过的URL Rewrite,我见过类似这样的域名: xxx.com/Archive/2008/03/21/,一直不知道怎么实现的,正好借这次机会研究一下。

从前天开始就一直在努力,基本上是第一天差了大半天资料,这篇文章写得非常详细,向作者致敬!第二天终于上手做出Demo,但有Bug,第三天解决了Bug,完美运行^_^

其实简单点说,个人觉得对于ASP.NET开发者实现URL Rewrite基本有3种途径:

1. 修改IIS ISAPI扩展,例如把”.xx”交给aspnet_isapi.dll ISAPI 扩展,就成了这样:”xxx.htm?q=blah”,这样就是最简单直接的SEO,但由于我是虚拟主机所以我仅仅只在本地试了下,不知道精英科技的管理面板是否支持,我没有试。
2. 修改WebConfig,添加


View Post»



Permalink:http://wayneye.com/ViewBlog.aspx?BlogID=9
Tag: