ตุลาคม 18, 2017, 11:36:40 pm *
ยินดีต้อนรับคุณ, บุคคลทั่วไป กรุณา เข้าสู่ระบบ หรือ ลงทะเบียน
ส่งอีเมล์ยืนยันการใช้งาน?

เข้าสู่ระบบด้วยชื่อผู้ใช้ รหัสผ่าน และระยะเวลาในเซสชั่น
   หน้าแรก   ช่วยเหลือ เข้าสู่ระบบ สมัครสมาชิก  
หน้า: [1]   ลงล่าง
  พิมพ์  
ผู้เขียน หัวข้อ: Thread Updates GUI and Form Closed  (อ่าน 853 ครั้ง)
0 สมาชิก และ 1 บุคคลทั่วไป กำลังดูหัวข้อนี้
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8267


ShadowWares


| |
« เมื่อ: กันยายน 26, 2016, 08:20:07 am »

การ Update UI จาก Thread ได้เขียนบทความสั้นไว้หลายตอนแล้ว แต่ยังไม่ได้เขียนเกี่ยวกับปัญญหาที่อาจจะเกิดขึ้นเมื่อใช้ Thread ในการ Update UI แบบต่อเนื่อง และ Form หรือ UI Component ตัวที่ถูกเข้าถึงจาก Thread ถูกทำลายเช่น Form ถูกปิด (เมื่อ Form ถูกปิด UI ที่อยู่บน Form จะถูกทำลายด้วย) ในขณะที่ Thread กำลังรันอยู่

ตัวอย่างปัญหา:


วิธีที่ 1 ใช้ try/catch:
เมื่อ Form ถูกปิด object ต่างๆ จะถูกทำลาย การที่ Thread พยายามเข้าถึงสิ่งที่ถูกทำลายไปแล้วย่อมส่งผลให้เกิดปัญหา
แก้ได้โดยทำการหยุดการทำงานของ Thread โดยใช้ Abort()
IsDisposed จะเป็น false เมื่อ Form ถูกปิด/ทำลาย จึฃนำมาใช้เป็นเงื่อนไขสำหรับ wile() ได้ รายละเอียดตาม code ต่อไปนี้

Code: (c-sharp)
    public partial class FormMain : Form
    {

        Thread MainThread;

        public FormMain()
        {
            InitializeComponent();
            MainThread = new Thread(MainLoop);
            MainThread.Start("Hello");
        }

        void MainLoop(Object obj)
        {

            while (!IsDisposed)
            {
                try
                {
                    Invoke((MethodInvoker)(() => {
                        /* Access GUI components here */
                    }));
                }
                catch (ObjectDisposedException)
                {
                    MainThread.Abort();
                }
                Thread.Sleep(20);
            }
            MainThread = null;
        }
    }




วิธีที่ 2 ทำการ override OnClosing
ในขณะที่ Form กำลังถูกปิด (กระบวนการทำลายกำลังทำงาน) OnClosing() จะถูกเรียก จึงสามารชิงทำลาย Thread เสียก่อนได้ โดยใช้ Abort() ตามตัวอย่างต่อไปนี้

Code: (c-sharp)
    public partial class FormMain : Form
    {

        Thread MainThread;
        bool Running;

        public FormMain()
        {
            InitializeComponent();
            MainThread = new Thread(MainLoop);
            MainThread.Start("Hello");
        }
        void MainLoop(Object obj)
        {
            Running = true;
            while (Running)
            {
                Invoke((MethodInvoker)(() => {
                    /* Access GUI components here */  
                }));

                Thread.Sleep(20);
            }
            MainThread = null;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            MainThread.Abort();
            base.OnClosing(e);
        }
    }



บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
หน้า: [1]   ขึ้นบน
  พิมพ์  
 
กระโดดไป: