Nine MVP's Blog

26/06/2006

– มาติด Turbo ให้ App ตอน Start App ด้วย NGen Tool (จะหายสงสัยทำไม .NET ไม่เปิดปุ๊บติดปั๊บแบบ VB6)

Filed under: Uncategorized — Nine MVP @ 10:58 pm
มีเสียงบ่นกันมากมายเหลือเกินนะครับ ทำไม ๆ ๆ เปิดโปรแกรมแล้วมันช้างี้ หน่วง ๆ มากมาย ไม่เห็นเหมือน VB6 เลย
แบบเรียกปุ๊บโผล่ปั๊บ เปิดปั๊บติดปุ๊บ อะไรทำนองนี้ จะได้หายสงสัยกันซะที
มาเข้าเรื่องกันเลยดีกว่า
 
พระเอกของเรางานนี้คือ NGen.exe Tool
เจ้าตัว NGen tool นั้นได้มีติดมากับ .Net Fx ทุก version ซึ่ง Tool ตัวนี้มีมาตั้งแต่สมัย .Net fx 1.0  แล้ว
และ MS ก็ใช้มันทำ Core dll ต่าง ๆ ของ .Net Fx ในตอนติดตั้งด้วยซึ่งจะ build ลง GAC นั้นเอง
 
เป็นที่ทราบกันดีว่า JIT(Just-In-Time) ถูกใช้เป็น Compiler เพื่อทำการคอมไพล์ MSIL Code (Exe, DLL) ของโปรแกรมที่เราสร้างขึ้นจาก .NET
และจะแปลง MSIL Code เหล่านี้ไปเป็น Native Code ของเครื่อง ก่อนที่จะทำการ execute code นั้น ๆ
ตัว code ส่วนนี้จะถูกสร้างขึ้นชั่วคราวทุกครั้ง ที่มี Process การทำงานเรียกใช้ในครั้งแรก
และจะถูกทำลายทิ้งเมื่อจบโปรเซส(ใน .net fx 2.0 จะมีการเก็บ code นี้ไว้ใน temp ไว้เพื่อให้ใช้งานทำให้เปิดโปรแกรมครั้งที่ 2 ทำได้รวดเร็วขึ้น แต่จะถูกลบเมื่อมีการ reboot เครื่องใหม่)
 
ตัว NGen นั้น พูดได้ว่าเป็นการข้ามขั้นตอนการ Compile exe,dll ต่าง ๆ ที่เราเรียกใช้
จาก JIT คือเราจะไปทำ Image ไว้ให้ CLR เรียกใช้โดยตรงได้เลย จากใน GAC
 
อธิบายการทำงานของ NGen
เราจะเรียกว่า เป็นการทำ Precompile หรือ pre-JITing
คือการสร้าง native code ของ MSIL ไว้บนเครื่องที่มีการใช้งานโปรแกรม
และผลทีได้จาก pre-JITing จะเป็น native code ซึ่งใช้แทนการ compile code ของ JIT ทุกครั้งที่มีการรันโปรแกรม
ตัว Native code ที่ได้จาก Ngen จะเป็น Win32 PE code จริง ๆ ซึ่งเช่นเดียวกับ VB6 (เปิดปุ๊บติดปั๊บ)
แต่เราจะเรียกกันว่า native images หรือ ngen images
ซึ่งจะถูกเก็บลงไปเป็น native image cache หรือ Ngen cache (GAC)
ขั้นตอนการทำงานขณะสร้าง Native Images ของ NGen
1. ต่อมาจะเรียก JIT มาทำการ Compile MSIL Code เพื่อสร้าง native code จาก exe หรือ dll
2. ซึ่งเมือ่ได้ทำการสร้าง native image แล้วก็เก็บลง native image cache (GAC)
 
ขั้นตอนการทำงานเมื่อเราเรียกใช้ Application ที่ได้สร้าง Native Images ไว้
เมื่อมีการเปิด App หรือจะ load DLL ตัว CLR จะทำการค้นหาที่ตั้งของ exe/dll ที่ได้ทำ Image ไว้แล้วไป query  ใน Native Image Cache และจะทำการ Load Image จาก GAC มาใช้งาน
 
 
มาดูกันใช้ยังงัย NGen ใน .NET FX 2.0

เราสามารถใช้ NGen ใน command line (DOS) ครับโดยตัว NGen.exe จะอยู่ที่ C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

โดยที่เราสามารถจะใช้กับ Exe, DLL ก็ได้ครับ เพราะเป็น MSIL เหมือนกัน(ยังไม่ขอพูดถึงคำสั่ง update)
 
คำสั่งที่ใช้ในการ Install ก็คือ
>NGen install fileName.exe
คำสั่งที่จะใช้ Uninstall ก็คือ
>NGen uninstall fileName.exe
 
หลังจากได้ ติดตั้งดูแล้วก็ใช้คำสั่ง Display เพื่อดูว่า Native Images ที่เราสร้างนั้นได้ติดตั้งลงใน GAC จริงหรือยังด้วยคำสั่ง
>NGen display fileName.exe
หรืออยากเห็นอะไรแบบเป็นรูปร่างมากกว่า DOS ก็ไปดูได้ที่
Administrative Tools -> Microsoft .NET Framework 2.0 Configuration ->
แล้วก็ดูใน List หาชื่อ exe / dll ที่ใช้ จะพบว่า Native Image ของเราลง GAC ไปเรียบร้อยแล้ว
 
แล้วต่างกันยังงัย กับเอา DLL ลง GAC เองเลย
DLL ที่เราเอาลง GAC เองนั้น เพียงแค่ทำการ Share กันใช้ระหว่าง appต่าง ๆ เท่านั้น และยังคงต้องผ่านการ Compile จาก JIT เพื่อสร้าง Native Code อยู่ครับ และมี Cache Type เป็น GAC สามารถ remove ได้ทันที จาก Microsoft .NET Framework 2.0 Configuration หรือ GACUtil
 
แต่ Native Image ที่เราได้สร้างขึ้นนั้นนอกจะจะสามารถ share กันใช้งานได้แล้ว อีกทั้งยังไม่ต้องผ่านขั้นตอนการ Compile จาก JIT และมี Cache Type เป็น Zap(ทำไมใช้ชื่อ แซ่บ ก็ไม่รู้สิครับ)  และไม่สามารถ remove ออกได้จาก tools ของ GAC แต่ต้อง uninstall โดยใช้ NGen เท่านั้น
 
เท่านี้เราก็สามารถ เปิด App แบบทันใจใช้งาน เหมือน VB6 แล้ว (ไม่น้อยหน้าเรื่องความเร็วกันแล้วนะ หุหุ)
 
 
ปล. ผิดพลาดประการใด ขออภัยไว้ ณ ที่นี้ด้วยครับ ผมก็เพิ่งจะใช้เหมือนกัน หุหุ

22/06/2006

การ Assign ค่าให้กับ member ใน class (C#) ระหว่าง Class

Filed under: Computers and Internet — Nine MVP @ 8:12 am
คำถาม

คือว่าผมมี class อยู่ 2 class ซึ่งทั้งสอง class นี้ถูก generate มาจาก schema (.xsd)

ซึ่งทั้งสอง class นี้ก็จะมี member ที่ชื่อเหมืนอกัน ยกตัวอย่างเช่น
A.CustomerID,B.CustomerID เป็นต้น
คือผมอยากเขียน function ที่ทำหน้ากำหนดค่าในคลาส A ที่มีชื่อ member เหมือนกันกับในคลาส B  
A.CustomerID = B.CustomerID แบบนี้ อ่ะครับ
ส่วนชื่อสมาชิกใน class ตัวไหนไม่เหมือนกัน ก็ไม่ต้องทำอะไร
คือว่ามันเยอะมากผมไม่อยากมานั่งพิมพ์เองเวลาเขียนโปรแกรมก็เลยอยากทำเป็น function ขึ้นมา
ไม่ทราบว่าต้องทำอย่างไรบ้างครับ ขอบคุณล่างหน้าครับ
 
 
ตอบ
 

รู้สึกข้อนี้จะต้องการ Function ที่หาชื่อของ Field Member ในแต่ละ Class มา assign ค่า จาก object ต้นทาง ไป object ปลายทาง ถ้าใช่ก็ให้ลองดู System.Reflection นะครับ

ทำตัวอย่างมาให้ดูนะ
 

class A

{

    public string mFName;

    public string mLName;

}

class B

{

    public string mFName;

    public string mLName;

}

 

Public Class AA

{

public void AA()

{

    A aa = new A();

    aa.mFName =

"ทดสอบ1";

    aa.mLName = "ทดสอบ2";

    B bb = new B();

    CloneField(aa, bb);

}

public bool CloneField(object objMaster, object objCopy)

{

    foreach (Reflection.FieldInfo om in objMaster.GetType.GetFields)

    {

        foreach (Reflection.FieldInfo oc in objCopy.GetType.GetFields)

        {

            if (om.Name == oc.Name & om.IsPublic & oc.IsPublic)

            {

                Type.GetType.InvokeMember(om.Name, Reflection.BindingFlags.SetField, null, objCopy, new object[] { om.GetValue(objMaster) });

            }

        }

    }

}

}

 

จะป้องกันการซ้ำกันของ MDI Form ใน VS 2003 ทำยังงัยดี

Filed under: Computers and Internet — Nine MVP @ 8:08 am
ลอง demo ง่าย ๆ นะ

เวลาใช้ก็แค่ 2 บรรทัดครับ
 
Class FormManager
 
 Public Class FormManager

    Private fMDI As Form

    ‘ส่ง MDI Form เข้ามา

    Public Sub New(ByVal mdiF As Form)

        fMDI = mdiF

    End Sub

    ‘สั่ง active form ที่ต้องการ

    Public Function ActiveForm(ByVal af As Form) As Boolean

        ‘หา form ที่ active อยู่ใน MDI

        For Each f As Form In fMDI.MdiChildren

            ‘ถ้าเจอ type เดียวกันเปิดอยุ่

            If f.GetType Is af.GetType Then

                ‘ให้ active ขึ้นมาโชว์

                f.Activate()

                GC.ReRegisterForFinalize(af)

                Return True

            End If

        Next

        ‘ถ้าไม่เจอ ให้ส่งเข้าไปเป็น child ของ MDI และ show ขึ้นมา

        af.MdiParent = fMDI

        af.Show()

        Return False

    End Function

End Class

 

HowTo Use
 
ที่ MDI Form ใส่ code นี้ จะเป็นการสร้าง instance ของ FormManager พร้อมทั้งส่ง MDI ที่จะทำงานเข้าไป

Private fm As New FormManager(Me)

 

และที่ปุ่ม menu ตอนจะเรียก form เช่น เราต้องการจะเรียก ProductForm จาก Menu Product ก็สั่งแค่ นี้ครับ

fm.ActiveForm(New ProductForm)

Create a free website or blog at WordPress.com.