Most popular

วันพฤหัสบดีที่ 5 พฤษภาคม พ.ศ. 2554

จัดการ C# Multi-Threading GUI เพื่อการใช้งานจริง (PART III)

ในตอนที่แล้วผู้เขียนได้ทดสอบการใช้ Thread กับ delegate ไปแล้ว ซึ่งเป็นรูปแบบการใช้ Thread ของ C# ซึ่งก็มีความต่างจากภาษาอื่นเพราะไม่ยอมให้ทำการ Inheritance เพื่อทำการ Implement เพื่อเป็น Thread Class ขึ้นมาใหม่ แต่ก็ใช่ว่าจะทำแบบอ้อมๆ ไม่ได้

ในการใช้งาน Thread ตอนนี้ ผู้เขียนจะให้ Thread ทำงานกับ DataGridView และ DataTable โดยผ่าน Class ที่สร้างขึ้นมาโดยเฉพาะ และผู้เขียนได้สร้างฟอร์ม พร้อมกับวาง Control DataGridView ตามภาพด้านล่างนี้

จากนั้นสร้าง Class makeTable ต่อจาก Class ของฟอร์ม
public partial class Form2 : Form
{
     public Form2()
     {
           InitializeComponent();
     }
}

class makeTable
{

}

ตอนนี้ผู้เขียนยังไม่ได้ยุ่งเกี่ยวกับ Class ของฟอร์ม แต่จะทำการ Implement Class makeTable ก่อน
จุดประสงค์ของ Class makeTable นี้คือการสร้าง Table สำเร็จรูปเพื่อจะส่งไปแสดงที่ DataGridView บนฟอร์ม และสามารถใส่ค่าให้แต่ละ Column ได้ด้วย

สิ่งสำคัญที่จะทำให้ Class ที่เราสร้างมีความยืดหยุ่นคือการสร้าง Member ของ Class
ผู้เขียนได้ประกาศ Member ของ Class และทำ Encapsulate Field ดังนี้

#region Member Class 
string[] colTXT = { "FIRST", "SECOND", "THIRD", "FOUR" };
private DataTable tb;
private DataGridView dgv;
private int rowcount;

public int Rowcount
{
     get { return rowcount; }
     set { rowcount = value; }
}

public DataGridView Dgv
{
     get { return dgv; }
     set { dgv = value; }
}

public DataTable Tb
{
     get { return tb; }
     set { tb = value; }
}
#endregion 

ผู้เขียนประกาศส่วนที่เป็น delegate method ไว้แยกกับ Member เพื่อให้ชัดเจน

#region delegate
public delegate void addRow();
public addRow AddRow;
#endregion

ส่วนของการประกาศ Member ของ Class ทั้งหมดตามภาพด้านล่าง
สิ่งที่ต่อมาที่จะต้องสร้างให้ Class makeTable คือ Constructor
Construct ที่สร้างขึ้นจำเป็นต้องรับ Parameter ได้ 2 ค่าคือ DataGridView และค่าตัวเลขจำนวนเต็ม เพื่อใช้ระบุจำนวน Row ที่ต้องการใน Table
public makeTable(DataGridView dataGridView, int rowCount)
{
        //ผ่านค่า Parameter ให้กับ Member ของ Class
        rowcount = rowCount;
        dgv = dataGridView;  

        //สร้าง Table ผ่าน Instance ที่เป็น Member ของ Class และกำหนดชื่อเป็น " RANDOMTABLE "
        tb = new DataTable("RANDOMTABLE");

        //สร้าง Column โดยใช้ค่าของ  colTXT
        DataColumn[] col = new DataColumn[colTXT.Length];
        for (int i = 0; i < colTXT.Length; i++)
        {
               col[i] = new DataColumn(colTXT[i], System.Type.GetType("System.Int32"));
        }
        tb.Columns.AddRange(col);

       //กำหนด Table ให้กับ DataGridView
       dgv.DataSource = tb;
}

ถึงตอนนี้ Class makeTable มีทั้ง Member ของ Class และมี Constructor ให้สามารถใช้งานได้แล้ว
ทดสอบการเรียกใช้งาน makeTable ผ่าน Constructor ของฟอร์ม จะได้ผลเป็นโครงสร้างของ Table ที่แสดงใน DataGridView
public partial class Form2 : Form
{
      public Form2()
      {
              InitializeComponent();

              //สร้าง Instance พร้อมส่ง Parameter ให้ Constructor
              makeTable MTB = new makeTable(this.dataGridView1, 100);
       }
}


 ในตอนนี้ ผลที่ได้คือโครงสร้างของ Table ที่มี 4 Column แต่ยังไม่มีข้อมูลใดๆ
คราวนี้ผู้เขียนจะเพิ่มความสามารถในการเพิ่ม Row ข้อมูล ให้กับ Class makeTable โดยเพิ่ม Method assignRow() เข้าไป

void assignRow()
{
      int i = 0;

      //ลูปจะทำงานจนได้จำนวน Row ที่ต้องการ
      while (i < rowcount)
      {
             Random rd = new Random();  //สร้าง Instance สำหรับสุ่มตัวเลข
             DataRow dr = tb.NewRow();   //สร้าง Row ใหม่ ให้ DataTable

             dr[0] = i;  //Column แรกใส่ค่า Index ของ Row

             //Column ที่เหลือให้ใส่ค่าที่ได้จากการสุ่ม
             for (int c = 1; c < colTXT.Length; c++)
             {
                   dr[c] = rd.Next(99999);
             }
             tb.Rows.Add(dr);   //เพิ่ม Row ให้ DataTable
             i++;
       }
       dgv.DataSource = tb;   //กำหนด Table ให้กับ DataGridView
}

คงยังไม่ลืมว่าใน Class มีการประกาศ delegate ไว้ด้วย ผู้เขียนจึงสร้าง delegate AddRow ให้ชี้มาที่  assignRow()  ส่วนนี้เพิ่มเข้าไปที่ Constructor

AddRow = new addRow(assignRow);

จากนั้นจะได้ Class makeTable ที่สมบูรณ์ พร้อมที่จะนำไปใช้งาน
 จากที่ได้ทดสอบที่ผ่านมา สิ่งที่ได้คือโครงสร้างของ Table ใน DataGridView ตอนนี้ผู้เขียนจะเรียกใช้ในส่วนของการเพิ่มข้อมูลเข้าไปอีก โดยเพิ่มเติมไปที่ Constructor ของฟอร์ม
public partial class Form2 : Form
{
      public Form2()
      {
            InitializeComponent();
            makeTable MTB = new makeTable(this.dataGridView1, 100);

            //สร้าง Thread t เพื่อให้ทำงานกับ Method AddRow
            Thread t = new Thread(new ThreadStart(MTB.AddRow));
            //ให้ Thread t ทำงาน
            t.Start();
       }
}

ผลการรันโปรแกรม ใน DataGridView จะมีจำนวน Row ข้อมูล 100 แถวตามผู้เขียนที่กำหนด (โดยค่า Row Index คือ 0 ถึง 99)
สรุป
การสร้าง Thread ใน C#.Net นั้นต่างจากการสร้าง Thread ในภาษาอื่นๆ ซึ่งส่วนใหญ่ C# ใช้การชี้ตำแหน่งในการให้ Thread ใช้ทำงาน การใช้งาน Multi-Thread จำเป็นต้องนำไปใช้อย่างเหมาะสม และมีการแยกแยะ Process เป็นอย่างดี มิเช่นนั้นอาจจะนำมาซึ่งข้อมูลที่ผิดพลาดได้

หากมีโอกาส ในบทความถัดไปผู้เขียนจะได้นำเสนอการสร้าง Thread เพื่อใช้งาน ในมุมของภาษา Java และ Delphi Pascal ต่อไป

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

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