BackgroundWorker คืออะไร
ก่อนจะไปทำความรู้จักกับเจ้า BackgroundWorker อยากจะขอถามผู้อ่านว่า
เคยประสบปัญหาเวลาเขียนโปรแกรมที่มีการทำงานงานๆ เช่น การดาวน์โหลดข้อมูล
หรือประมวลผลทรานแซคชั่น (Transactions) จำนวนมากๆ แล้วเมื่อนำไปใช้งาน โดยผู้ใช้ (Users) บ่นว่า ทำไมโปรแกรมมันค้าง ทำอะไรต่อไม่ได้เลย ต้องรอให้มันทำงานเสร็จก่อนถึง
จะไปทำงานอย่างอื่นได้ ถ้าท่านเคยประสบปัญหาแบบนี้ เจ้าตัว BackgroundWorker อาจช่วยท่านได้ระดับหนึ่ง
BackgroundWorker เป็น Component Class นึงที่อยู่ใน System.ComponentModel
หากเปิดหน้า Design ใน VS.NET จะมี Control อยู่ในส่วน Components ของ Toolbox
BackgroundWorker นั้นเป็นคลาสที่ช่วยให้โปรแกรมเมอร์สามารถรันการดำเนินการ (Operation) บนเธรด (Thread) ใหม่ ซึ่งจะช่วยแก้ปัญหาที่กล่าวมาในตอนแรกได้
โดย BackgroundWorker จะมี Events สำคัญอยู่ 3 ตัวคือ
Dowork ทำหน้าที่รันการดำเนินการแบบ Background อีเว้นท์ถัดไปคือ ProgressChanged จะทำหน้าที่เมื่อมีการรายงานความคืบหน้าของการดำเนินการที่ทำงานอยู่
ส่วนอีเว้นท์สุดท้ายคือ RunWorkerCompleted จะทำงานเมื่อ การเดินเนินการที่ทำงานอยู่เสร็จสมบูรณ์
เพื่อให้เห็นภาพการทำงาน เรามาสร้างโปรแกรมง่ายๆ ขึ้น เพื่อจะได้เข้าใจการทำงานของมัน
1. สร้าง Window Application project ขึ้นมาก่อน
2. จากนั้นให้ลาก Control จาก Toolbox มาวางตามรูป ซึ่งประกอบด้วย label , Button และ Progressbar
3. คราวนี้หากเราต้องการนับตัวเลขหนึ่งถึง 20 เมื่อกดปุ่ม โดยให้แสดงตัวเลขที่ label และให้ Progressbar แสดงความคืบหน้า โดยจะนับแต่ละตัวห่างกัน 1 วินาที
ซึ่งครั้งแรกเราจะยังไม่ใช้งาน BackgroundWorker แล้วมาดูผลว่าเป็นยังไง
ตัวอย่างโค้ด
Imports System.ThreadingPublic Class Form1
Private Sub btnDoWork_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDoWork.Click
pgbWork.Value = 0pgbWork.Maximum = 100lblStatus.Text = String.EmptyCountNumber()
End Sub
Private Sub CountNumber()
Dim intCount As Integer = 1Dim intMaxNum As Integer = 20
For intCount = 1 To intMaxNum
Display(intCount.ToString)UpdateProgress((100 / intMaxNum) * intCount)Thread.Sleep(1000)
Next
End Sub
Private Sub Display(ByVal strNum As String)
lblStatus.Text = strNum
End Sub
Private Sub UpdateProgress(ByVal intPercent As Integer)
pgbWork.Value = intPercent
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadpgbWork.Value = 0pgbWork.Maximum = 100End Sub
4. จะเห็นว่าเมื่อเรารันโปรแกรม แล้วกดปุ่ม DoWork โปรแกรมเหมือนจะค้างไป ไม่สามารถทำอะไรได้ เช่นเวลา Minimize ลงมาที่ Task Bar จะไม่สามารถ Active มันขึ้นมาได้ จนกว่าโปรแกรมจะทำงานเสร็จ
หรือตัว Label ไม่อัพเดทตามที่เราเขียนโค้ดไว้
5. คราวนี้มาถึงตาพระเอกของเราบ้าง เราจะเอา BackgroundWorker มาใช้งาน แล้วดูผลกันว่าแตกต่างกันอย่างไร
6. เริ่มด้วยให้ลาก Control Components ที่ชื่อ BackgroundWorker มาไว้ที่ฟอร์มของเรา จะสังเกตว่ามีไอคอน BackgroundWorker มาปรากฎในช่อง Component ด้านล่าง จากนั้นให้ตั้งชื่อ ในที่นี้ผมตั้งว่า
wrkSample
7. จากนั้นให้กำหนด Properties ของ BackgroundWorker โดยกำหนด WorkerReportsProgress เป็น True เพื่อที่เราสามารถอัพเดทค่าของ label ได้
8. ต่อไปให้กำหนดในส่วน Events โดยกดที่รูปสายฟ้า แล้วให้ทำการดับเบิ้ลคลิกที่ช่องว่างๆ หลังชื่อ Event เราจะได้ Event มา 3 ตัวและมีการสร้างให้อันตโนมัติในส่วน Coding
Private Sub wrkSample_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles wrkSample.DoWork
End Sub
Private Sub wrkSample_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles wrkSample.ProgressChanged
End Sub
Private Sub wrkSample_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles wrkSample.RunWorkerCompleted
End Sub
9. มาเริ่มในส่วน Coding กัน เริ่มแรกคือ การเรียกใช้งาน BackgroundWorker เมื่อมีการกดปุ่ม DoWork
If wrkSample.IsBusy <> True Then
' Start the asynchronous operation.
wrkSample.RunWorkerAsync()
End If
10. เมื่อเรียกใช้ Method ชื่อ RunWorkerAsync โปรแกรมจะเรียกใช้งานอีเว้นท์ชื่อ wrkSample_DoWork ทันที ซึ่งการทำงานหลักๆ เราจะเขียนไว้ที่นี้
Private Sub wrkSample_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles wrkSample.DoWork
Dim intCount As Integer = 1
For intCount = 1 To intMaxNum
wrkSample.ReportProgress(intCount)
Thread.Sleep(1000)
Next
End Sub
11. จะเห็นว่ามีการเรียก Method ชื่อ ReportProgress โดยเมื่อเรียกใช้งาน โปรแกรมจะเรียกใช้งานอีเว้นท์ชื่อ wrkSample_ProgressChanged ทันที ซึ่งใน Event นี้เองที่เราสามารถอัพเดท label และ progressbar ได้
Private Sub wrkSample_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles wrkSample.ProgressChanged
lblStatus.Text = e.ProgressPercentage.ToString() '// ค่าที่ส่งมาทาง Parameter ของ Method ชื่อ ReportProgress
pgbWork.Value = (100 / intMaxNum) * e.ProgressPercentage
End Sub
12. สุดท้ายเมื่อโปรแกรมทำงานเสร็จสิ้นจะมีการเรียกใช้งานอีเว้นท์ที่ชื่อ wrkSample_RunWorkerCompleted โดยเรามาสามารถอัพเดทค่าของ Control ต่างๆ ได้เช่นกัน
Private Sub wrkSample_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles wrkSample.RunWorkerCompleted
lblStatus.Text = "Completed"
End Sub
13. ทดลองรันโปรแกรม จะเห็นว่า Label นั้นเปลี่ยนไปตามที่เรากำหนดไว้ โดยไม่มีอาการค้างให้เห็นแต่อย่างใด
หวังว่าบทความนี้จะมีประโยชน์แก่ผู้อ่านนะครับ
อ้างอิง
มีประโยชน์แต่เข้าใจยากแหะ
ตอบลบ