Wednesday, December 4, 2013

เพิ่ม web request bandwidth


<system.net>
  <connectionManagement>
    <add address="*" maxconnection="30" />
  </connectionManagement>
</system.net>

Monday, January 14, 2013

Event Source Installer และ installutil command

เมื่อ solution ที่เราเขียน ต้องการการติดตั้งบางอย่างบนเครื่องที่เราจะใช้รัน เราสามารถสร้าง installer เพื่อทำการเตรียน Environment ให้โปรแกรมเราได้ เช่นตัวอย่างจะใช้สร้าง Event Source เพื่อใช้เก็บ Event Log

1. สร้าง class ที่ implement Installer ใน solution ที่เราเขียน

using System;
using System.Configuration.Install;
using System.Diagnostics;
using System.ComponentModel;

[RunInstaller(true)]
public class MyEventLogInstaller: Installer
{
    private EventLogInstaller myEventLogInstaller;

    public MyEventLogInstaller() 
    {
        // Create an instance of an EventLogInstaller.
        myEventLogInstaller = new EventLogInstaller();

        // Set the source name of the event log.
        myEventLogInstaller.Source = "NewLogSource";

        // Set the event log that the source writes entries to.
        myEventLogInstaller.Log = "MyNewLog";

        // Add myEventLogInstaller to the Installer collection.
        Installers.Add(myEventLogInstaller);   
    }
}


2. หลังจาก build จะได้ assembly .exe หรือ .dll เราก็สามารถใช้ ตัว VisualStudio Command prompt ติดตังตัว event source ลงบนเครื่องที่เราต้องการได้โดย run as admin แล้วรันคำสั่งต่อไปนี้



C:\xxx\bin>installutil App_Code.dll



3. ตัวอย่างผลรัน


C:\xxx\bin>installutil App_Code.dll
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.17929
Copyright (C) Microsoft Corporation.  All rights reserved.


Running a transacted installation.

Beginning the Install phase of the installation.
See the contents of the log file for the C:\xxx\bin\App_Code.dll assembly's progress.
The file is located at C:\xxx\bin\App_Code.InstallLog.
Installing assembly 'C:\xxx\bin\App_Code.dll'.
Affected parameters are:
   logtoconsole =
   logfile = C:\xxx\bin\App_Code.InstallLog
   assemblypath = C:\xxx\bin\App_Code.dll
Creating EventLog source SemanticLoggingEventLogPerfTests in log ...

The Install phase completed successfully, and the Commit phase is beginning.
See the contents of the log file for the C:\xxx\bin\App_Code.dll assembly's progress.
The file is located at C:\xxx\bin\App_Code.Install
Log.
Committing assembly 'C:\xxx\bin\App_Code.dll'.
Affected parameters are:
   logtoconsole =
   logfile = C:\xxx\bin\App_Code.InstallLog
   assemblypath = C:\xxx\bin\App_Code.dll

The Commit phase completed successfully.

The transacted install has completed.


Saturday, January 12, 2013

ตัวอย่าง match regex แล้ว assign ใส่ groups


ตัดมาจาก code ในส่วยที่เคยใช้ไป get ราคาหุ้น

    this.Html = HttpRequester.RequestHttp(string.Format(this.RequestUrl, tickerSymbol), out errorCode);
    if (errorCode < 0)
    {
        return errorCode;
    }
    string RegexPricePattern = @"<span class=""time_rtq_ticker""><span id=""[^>\t\r\n\v\f]*"">(?<price>\d*\.\d*)</span>?";
    Regex priceFinder = new Regex(RegexPricePattern, RegexOptions.IgnoreCase);
    Match priceMatch = priceFinder.Match(this.Html);
    if (priceMatch.Success)
    {
        string priceString = priceMatch.Groups["price"].Value;
    }


Tuesday, January 8, 2013

new modifier, static binding และ dynamic binding

ในตอนนี้จะพยายเขียนให้เข้าใจง่ายที่สุด สำหรับผู้ที่เพิ่งเริ่มให้เข้าใจกระบวนการ instantiate object

คำสั่งในภาษา C# เช่นคำสั่ง new อาจมีการใช้งานได้เกินหนึ่งรูปแบบซึ่งก็คือ
  1. ใช้ในการทำ method hiding
  2. ใช้สร้าง object
ในหัวข้อนี้ เราจะขอพูดถึงอย่างหลังก่อนนะครับแล้วในตอนท้าย จะค่อยสาธิตการทำ method hinding

ในการสร้าง object เราสามารถใช้คำสั่งแบบนี้

    new Beer();


จะเห็นว่า หลังคำว่า new จะเป็นชื่อของ constructor ของ class ที่เราต้องการสร้าง นั้นก็คือ Beer() ซึ่ง constructor คือ method ของ class ที่จะทำงานเมือเราต้องการจะสร้าง class นั้นๆ เช่น class Beer ข้างล่าง


    class Beer
    {
        String Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }
    }


จะเห็นว่า ใน class Beer มีสอง method ที่ไม่มี return type และมีชื่อเหมือนกันกับชื่อ class คือ "Beer()" และ "Beer(string name)" (constructor overload) นั้นหมายความว่า เราสามารถสร้าง object จาก constructor ตัวใดตัวหนึ่งจากสองตัวนี้ก็ได้ ทำให้การสร้าง object มีความยืดหยุ่น และสามารถประยุคเทคนิคในการสร้างและจัดการ object ได้หลากหลาย

จากตัวอยากข้างบน "new Beer()" code จะทำงานดังนี้

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  newobj     instance void SampleDynamicBinding.Beer::.ctor()
  IL_0006:  pop
  IL_0007:  ret
} // end of method Program::Main


ข้างบนนี้คือ MSIL ที่ได้หลังจาก compile คำสั่ง new Beer(); การทำงานคร่าวๆ ก็คือ
  1. เรียก constructor เพื่อสร้าง instance ของ class Beer
  2. จองและจัดสรรนหน่วยความจำ เพื่อเก็บ instance ของ Beer ในที่นี้คือ managed heap
  3. จบ

อ่าว แล้วงี้เราจะไปใช้ไอ้ตัว object นี้ได้ไงอ่ะ คำตอบคือ เราก็สร้างตัวแปร เพื่อที่จะอ้างอิงไปหาไอ้ instance ที่อยู่ใน heap นั้นไงล่ะ, ง่ายๆ ด้วย syntax ที่คุ้นเคย แบบนี้

    Beer beer = new Beer();


จะเห็นว่า มีส่วนเพิ่มขึ้นมาสามส่วนจากหน้าไปหลังคือ
  1. Beer คือ ชื่อของ type นั้นก็คือ class Beer ซึ่งต้องมี type ตรงกันกับกับ object ที่เราสร้างด้วยคำสั่ง new
  2. beer คือชือของตัวแปร
  3. เครื่องหมาย "=" คือการ assign ค่าอ้างอิงไปยัง instance ของ Beer ที่เราสร้างดังที่อธิบายไปแล้ว

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] class SampleDynamicBinding.Beer beer)
  IL_0000:  nop
  IL_0001:  newobj     instance void SampleDynamicBinding.Beer::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method Program::Main


MSIL ที่ compile ออกมาจะต่างออกไปหน่อย ซึ่งการทำงานคร่าวๆ จะเป็นประมาณนี้

  1. หลังจากที่มีการสร้าง instance ของ class และเก็บไว้ใน managed heap ไปแล้ว
  2. จองเนื้อที่ใน stack เพื่อเก็บตัวแปร "beer" ซึ่งมี type เป็น Beer
  3. ทำการกำหนดค่า reference ของ beer ไปยัง instance ในข้อ 1.
ทีนี้ เราก็สามารถใช้ instance ของ class Beer ได้แล้ว โดยการใช้ผ่านตัวแปร beer นั้นเอง ซึ่งการกำหนดค่าอ้างอิงของ instance ไปยังตัวแปรที่มี type ตรงกัน เราเรียกว่า name binding 

การ binding แบ่งออกเป็น 2 แบบคือ static binding และ dynamic binding
  1. Static binding คือ การ กำหนดค่าอ้างอิงไปยังตัวแปลได้เลย ขณะ compile time ดังตัวอย่างข้างต้น
  2. Dynamic binding คือ การกำหนดค่าอ้างอิงไปยังตัวแปลของ object ขณะ run-time ซึ่งวิธีนี้ ทำให้การออกแบบซอร์ฟแวรได้ยืดหยุ่น และหลากหลาย สนับสนุนหลักการ polymorphism เช่น dependency injection เป็นต้น
ตัวอย่างด้านล่าง จะเป็นการสาธิตการทำ dynamic binding และการทำ method hiding ด้วย new modifier นะครับ จาก class Beer เราจะเพิ่ม class ที่ชือว่า Singha เข้ามา ซึ่งนี้ implement class Beer อยู่ (inherit) 

    class Beer
    {
        string Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }

        public void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Singha : Beer
    {
        string Name; 

        public Singha() : this("Singha")
        {
        }

        public Singha(string name)
        {
            this.Name = name;
        }

        public new void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }


บรรทัดข้างล่างนี้ เป็นการสร้าง instance ของ class Singha แล้ว assign ใส่ตัวแปลที่ชื่อว่า beer ซึ่งมี type เป็น Singha

    Singha beer = new Singha();


ซึ่งกระบวนการสร้าง object แบบนี้จะต่างจากแบบก่อนหน้านิดหน่อย เพราะว่า class Singha implement class Beer ทำให้เวลาสร้าง object Singha ใน heap จะมีการสร้างและเรียก constructor ของ class แม่มันด้วย ซึ่งก็คือ Beer ทำให้ใน managed heap มี instance อยู่สองตัว คือ
  1. instance ของ class Singha
  2. instance ของ class Beer
นั้นหมายความว่า ถ้าเราใช้ตัวแปร เป็น type ของ Beer เราก็สามารถที่จะเลือกเสียบไปยัง instance Singha หรือ Beer ใน heap ก็ได้ ซึ่งนั้นก็คือ dynamic binding เป็นผลเนื่องมาจาก compiler มีการทำ implicit type conversion

    Beer beer = new Singha();


แต่เราไม่สามารถทำแบบนี้ได้

    Singha beer = new Beer();


เพราะว่า เราเรียก constructor ของ Beer จะไม่มีการสร้าง instance ของ class Singha, การทำ type conversion จะเป็นจาก base class ไป derived class เท่านั้น  ไม่งั้นจะเกิด error แบบนี้
Cannot implicitly convert type 'SampleDynamicBinding.Beer' to 'SampleDynamicBinding.Singha'. An explicit conversion exists (are you missing a cast?)

ตัวอย่าง

    Singha beer = new Singha();
    beer.WriteName();               // dynamic type คือ Singha
    ((Beer)beer).WriteName();       // dynamic type คือ Beer


ผลรัน


    Singha
    Noname

นอกจาก method hiding ก็ยังมีการทำ method overriding อีกตัว ซึงเป็นการเปลี่ยนการทำงานของ method ใน derived class ต่างจากการทำ hiding ที่จะทับการทำงานเดิม

ตัวอย่าง

    Beer beer = new Singha();
    beer.WriteName();               // dynamic type คือ Singha
    ((Beer)beer).WriteName();       // dynamic type คือ Beer


ผลรัน

    Noname
    Noname

ผลรันเป็น Noname ทั้งสองบรรทัดเนื่องจาก class Singha มีการทำ method hinding ทำให้ complier มองเป็นคนละ method กัน ถึงแม้จะเรียกใช้ constructor ของ Singha ซึ่งจะมีการ  implicit type conversion จาก Beer เป็น Singha แต่ method ที่ถูกเรียกจะเป็น Beer.WriteName() 

ตัวอย่างด้านล่างคือการทำ method overriding

    class Beer
    {
        string Name;

        public Beer() : this("Noname")
        {
        }

        public Beer(string name)
        {
            this.Name = name;
        }

        public virtual void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Singha : Beer
    {
        string Name; 

        public Singha() : this("Singha")
        {
        }

        public Singha(string name)
        {
            this.Name = name;
        }

        public override void WriteName()
        {
            Console.WriteLine(this.Name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Beer beer = new Singha();
            beer.WriteName();               
            ((Beer)beer).WriteName();       
        }
    }
 

ผลรัน


    Singha
    Singha

จะเห็นว่าการทำ method overriding จะเป็นการทับการทำงานของ method เดิม 

Monday, January 7, 2013

ความแตกต่างระหว่าง Windows 64bit กับ 32bit กับซีพียู 64บิต และ 32 บิต


เนื้อหาตอนนี้ ยังไม่เกียวกับ coding โดยตรงนะขรับ แต่เป็นเรื่องราวที่ข้ากระผมและเพื่อนๆ เจอมาระหว่างไปซื้อคอมพิวเตอร์บ้าง อ่านเจอบ้าง หรือฟังจากทีวีบ้าง ซึ่งบ้างครั้งก็ถูกบ้างก็ผิด เลยเอามาเขียนเป็น article ซะเลย

หลายๆ คนมักจะมีคำถามเกียวกับ Windows 32bit กับ 64bit ว่าต่างกันอยากไร บ้างก็ได้รับคำตอบจากพนักงานขายคอมพิวเตอร์ หรือจากทางเวปบอร์ดต่างๆ ซึ่งก็ถูกบ้างไม่ถูกบ้าง อธิบายได้คร่าวๆ ได้ดังนี้ขรับ

1. ทำไมถึงมี Windows 64 bit, เนื่องจากปัจจุบัน โปรแกรมและเกม เริ่มมีการใช้หน่วยความจำมากขึ้น ซึ่งระบบปฏิบัตการ 32bit นั้นสามารถเข้าถึงหน่วยความจำได้สูงสุดเพียง 4GB เท่านั้น (2 ยกกำลัง 32) ซึ่งแต่ละโปรแกรม ซึ่งรวมถึงเกมด้วย จะสามารถใช้หน่วยความจำได้สูงสุดเพียง 2 GB เท่านั้น แต่ Windows 64bit จะสามารถใช้ได้ถึง 8TB ในสถาปัตยกรรม x64 และ 7TB ในสถาปัตกรรม Itanium ซึ่งจะอธิบายเพิ่มในหัวข้อถัดๆ ไป
ย้อนไปในสมัยอดีต Windows 3.11(16 bit), Windows NT3.1(32 bit) เครื่องคอมพิวเตอร์มี RAM ประมาณ 8MB, การที่แต่ละโปรแกรม สามารถใช้หน่วยความจำถึง 2 GB ถือว่ามากเกินพอ แต่ในสมัยปัจจุบัน 2 GB ก็เหมือนจะไม่พอในบางโปรแกรม ซึ่งทางออกก็คือ ทาง CPU ก็ต้องขยายบัสเพิ่มขึ้น เพือทำให้สามารถเข้าถึง RAM ได้มากขึ้น และทางระบบปฏิบัตการ ก็จำเป็นต้องขยายการเข้าถึงในส่วนนี้ด้วยเช่นกัน

นั้นหมายความว่า เครื่องที่จะติดตั้งระบบปฏิบัตการ 64 bit ได้ จะต้องมี Processor 64 bit เช่น Core2Duo, core i3,5,7 เป็นต้น

2. Windows 32 bit สามารถเข้าถึง หน่วยความจำได้ 4GB นั้นก็คือ 2 ยกกำลัง 32 จะเท่ากับ 4,294,967,296 bytes ซึ่งก็เท่ากับ 4 GB นั้นเอง ซึ่งตามปกติ Windows จะแบ่งเป็น
  1. Kernel mode 2 Gb - ส่วนของระบบปฏิบัตการ และ driver
  2. User mode 2 GB  - สำหรับโปรแกรมหรือเกม ที่ไม่เกียวกับระบบปฏิบัตการ
แต่หน่วยความจำ 4 GB นี้หมายถึง Virtual memory นะขรับ ไม่ได้หมายถึง RAM ซึ่ง Virtual memory นี้จะประกอบด้วยสองส่วนคือ
1. RAM
2. Page file ซึ่งอยู่ใน Hard-disk เรานั้นเอง
นั้นหมายความว่า เราเครื่องเรา มี RAM ตำกว่า 4 GB ควรจะลง 32bit เกิน 4GB ลง 64bit นี้ไม่ใช่นะครับ มี RAM เท่าไหร่ก็สามารถลง 64bit ได้ ต่อเมือ CPU เราเป็นสถาปัตยกรรมแบบ 64bit ทาง Windows แนะนำขั้นต่ำที่ 2 GB (http://windows.microsoft.com/systemrequirements)

3. Windows 64 bit สามารถเข้าถึงหน่วยความจำได้สูงสุด 16 TB ซึ่งจะสังเกตได้ว่า 2 ยกกำลัง 64 จะได้ 16EB (exabytes) ซึ่งมากกว่า 8 TB มาก แต่ปัจจุบันสถาปัตยกรรม x64 ที่เราใช้ๆ กันอยู่ สนับสนุน Virtual add space ที่ 48 bits ซึ่งเท่ากับ 256 TB แต่ Windows 64bit จะสนับสนุนเพียง 44 bits ซึ่งก็คือ 16 TB ซึ่ง Windows จะแบ่งเป็น
  1. Kernel mode 8 TB
  2. User Mode 8 TB
ซึ่งจะเห็นว่า ได้เพิ่มจากแบบ 32 bit มากมายเด้อขรับ แต่ไม่ได้หมายความว่า รองรับได้ไม่จำกัดเหมือนบางคนเข้าใจเด้อขรับ

4. Application 32 bit จะสามารถติดตั้งลง Windows 64 bits ได้หรือไม่ คำตอบคือได้ 100% ขรับ(ยกเว้นตัวที่ใช้ Hardware หรือหน่วยความจำโดยตรงโดยไม่ผ่าน OS) และที่ดีไปกว่านั้น ซึ่งก็คือมันสนับสนุน WOW 64 (Windows on Windows) ซึ่งจะเห็นได้ ตามโฆษณา CPU ของทั้ง intel และ AMD ซึ่งข้อดีขอมมันก็คือเอาไว้ host application 32bit และ application ที่ถูก host โดย WOW64 สามารถใช้หน่วยความจำได้เต็มที่ของ 32 bit ซึ่งก็คือ 4GB เต็ม เนื่องจากไม่ต้องมีการแบ่งส่วน 2 GB เดิมไปให้ kernel

5. นอกจากนี้ ขนาดของ Register ใน CPU จะมีขนาดต่างกันด้วย เป็นเหตุให้ driver ของ 32 บิต กะ 64 บิต ใช้ด้วยกันบ่ได๋

ความจริงมีเรื่องอื่นๆ ที่แตกต่างกันอยู่อีก ทั้งเกียวกับ coding และไม่เกี่ยว เอาไว้ต่อกันตอนหน้าเด้อขรับเด้อ