1 พฤศจิกายน 2554

C# .NET เขียนโปรแกรม winform ให้เปิดได้หน้าจอเดียว (mutex single instance app)

 ผมเขียนเรื่องนี้เพราะมีหลายคนถามไม่รู้จะ google หาคำว่าอะไร พฤติกรรมแบบนี้เรียกว่า "single instant application" ครับ

What?
สังเกตุมั้ยว่าโปรแกรม client ส่วนมากเปิด 2 จอ พร้อมกันไม่ได้ user จะต้องหาโปรแกรมเสริมอย่าง sandbox มาใช้เพื่อเปิดโปรแกรม 2จอพร้อมกัน ยกตัวอย่างเช่น msn, skype, camfrog ถ้าเราเปิดโปรแกรมขึ้นมาแล้ว ดับเบิ้ลคลิ้กซ้ำจะเป็นการโฟกัสหน้าจอหลักที่เปิดอยู่แทนที่จะรันโปรแกรมใหม่

How to?
ตัวอย่างโค้ด System.Threading.Mutex ใน .NET framework

/// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            bool isReady;
            var mutex = new System.Threading.Mutex(true, "MyApplicationName", out isReady);
            if (!isReady)
            {
                //Console.WriteLine("Another instance is already running.");
                return;
            }
            GC.KeepAlive(mutex); 

            //Run main form
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new UI.ReportForm());
        }
อธิบายโค้ด..
class System.Threading.Mutex มาจากคำว่า "mutual exclusion" ทำหน้าที่เป็น synchronization object ประสานงานระหว่าง thread หรือการทำ Thread safe
var mutex = new System.Threading.Mutex(true, "MyApplicationName", out isReady);
จากบรรทัดนี้เราสร้างตัวแปร mutex กำหนดชื่อ "MyApplicationName" ผ่าน constructor ทำให้ object mutex นี้ผูกติดกับ OS เพื่อใช้ตรวจสอบ Process ภายนอกโปรแกรม (interprocess synchroization) ว่ามี Mutex ชื่อนี้กำลังทำงานอยู่หรือไม่ (Note* ถ้าไม่กำหนดชื่อให้ mutex object จะมี scope แค่ภายใน current process เท่านั้น)
 ถ้ามี mutex ชื่อ "MyApplicationName" กำลังทำงานอยู่ใน process ใดก็ตาม(เช็คในระดับ OS) out isReady จะได้ค่าเป็น false ดังนั้นเราก็สั่ง return หยุดการทำงานซะก่อนที่จะเปิดหน้าจอซ้ำ
GC.KeepAlive(mutex);
ตรงนี้เป็นการป้องกัน Garbage Collector มาลบตัวแปร mutex object ของเราออกจากหน่วยความจำก่อนที่ user จะปิดโปรแกรม (GC จะคอยลบ object ไม่ได้ถูกเรียกใช้งาน)


Why/When? ทำไมต้องเปิดได้จอเดียว จำเป็นหรือไม่
ก่อนจะเขียนโปรแกรมต้องคิดถึง user ก่อนว่าทำไปเพื่ออะไร ไม่งั้น user จะโวยวาย(แล้วสุดท้ายก็เอา sandbox มาใช้เปิด 2จอ อยู่ดี)
1. transaction จำเป็นมั้ยที่แต่ละขั้นตอนต้อง commit ก่อน save มีการเช็ค session หรือสถานะการ login
2. client/server concurrent connection มีการจำกัดการเชื่อมต่อกับเซอฟเวอร์ (เช่น MSSQL license) หรือโปรแกรมเราใช้ bandwidth / performance
3. ถ้าลักษณะการทำงานเป็นแบบ MDI (multi document interface) ยกตัวอย่าง word, excel ไม่จำเป็นต้องล้อค mutex ครับอย่าลืมคิดถึง user เป็นหลัก


ยังมีอีกวิธีในการตรวจสอบจาก process table (running .exe) ว่าโปรแกรมถูกเปิดทำงานแล้วโดยใช้ System.Diagnostics.Process.GetProcessesByName() ใช้ได้เหมือนกันแต่ทำงานได้ช้ากว่า Mutex ที่ว่ามาลองศึกษาดูจากลิ้งค์อ้างอิงครับ

Reference :

ไม่มีความคิดเห็น:

แสดงความคิดเห็น