|
Windows Form App : การทำ ProgressBar แบบ Dialog ทำงานร่วมกับ BackgroundWorker (VB.Net, C#) |
Windows Form : การทำ ProgressBar Dialog ทำงานร่วมกับ BackgroundWorker (VB.Net, C#) ในตัวอย่างตอนที่สองของ BackgroundWorker จะเป็นการประยุกต์ใช้งานร่วมกับ ProgressBar และ Dialog ซึ่ง Interface นี้จะเหมาะกับโปรแกรมที่ทำงานนานพอสมควร และป้องกันในขณะที่โปรแกรมกำลังทำงาน ต้องการไม่ให้ User ทำการคลิกที่ส่วนอื่น ๆ ของหน้าจอ จะต้องรอจนกว่าโปรแกรมจะทำงานเสร็จและในช่วงที่รอนั้นหน้าจอของโปรแกรมจะไม่ค้าง สามารถแสดงสถานะของ ProgressBar การทำงานให้ User ได้ทราบ รวมทั้ง User สามารถทำการคลิก Stop หรือ Cancel ตัว Process และการทำงานก็จะหยุดลง โดยการออกแบบ Interface แบบนี้ค่อนข้างจะถือได้ว่าโปรแกรมเมอร์นั้นได้คำนึงถึงประสิทธิภาพของโปรแกรม และทำให้โปรแกรมค่อนข้างจะน่าใช้ บ่งบอกถึงความเป็นมืออาชีพและประสบการณ์ในการเขียนโปรแกรม
Windows Form App : การทำ ProgressBar แบบ Dialog ทำงานร่วมกับ BackgroundWorker
ตอนที่ 1 : Windows Form App : ทำให้หน้าจอไม่ค้างในขณะทำงานด้วย BackgroundWorker (VB.Net,C#)
ในตัวอย่างจะประกอบด้วย 2 ไฟล์ Form คือ
- frmMain (หน้าหลัก)
- ProgressDlg (เป็น Diilog แสดง Progress)
ออกแบบ Form
Form ของ ProgressDlg
ประกอบด้วย ProgressBar ID : progressStatus , Label ID : lblProgress และ Button ID : btnStop
Form ของ frmMain
ประกอบด้วย Button ID : btnStart , Label ID : lblStatus
Code ของ C#
ProgressDlg.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DemoProgressWorking
{
public partial class ProgressDlg : Form
{
// Update Progress Number
public string Message
{
set { this.lblProgress.Text = value; }
}
// Update Progress Status
public int ProgressValue
{
set { this.progressStatus.Value = value; }
}
// Stop Event
public EventHandler stopProgress;
public ProgressDlg()
{
InitializeComponent();
}
private void btnStop_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
if (stopProgress != null)
{
stopProgress(sender, e);
}
}
}
}
frmMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DemoProgressWorking
{
public partial class frmMain : Form
{
BackgroundWorker bgWorker;
ProgressDlg progressDlg;
public frmMain()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
// New BackgroundWorker
bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
// Start the asynchronous operation.
bgWorker.RunWorkerAsync();
// New Dialog
progressDlg = new ProgressDlg();
progressDlg.stopProgress = new EventHandler((s, e1) =>
{
switch (progressDlg.DialogResult)
{
// When click stop button from Progress Dialog
case DialogResult.Cancel:
bgWorker.CancelAsync();
progressDlg.Close();
break;
}
});
progressDlg.ShowDialog();
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 100; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(100);
worker.ReportProgress(i);
}
}
}
// This event handler updates the progress.
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.lblStatus.Text = "Processing...";
// Update status to Dialog
progressDlg.Message = (e.ProgressPercentage.ToString() + "%");
progressDlg.ProgressValue = e.ProgressPercentage;
}
// This event handler deals with the results of the background operation.
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
this.lblStatus.Text = "Canceled!";
}
else if (e.Error != null)
{
this.lblStatus.Text = "Error: " + e.Error.Message;
}
else
{
this.lblStatus.Text = "Done!";
}
progressDlg.Close();
}
}
}
คำอธิบาย
ProgressDlg : Code ส่วนนี้เป็นของ ProgressDlg ใช้สำหรับทำการ Update ตัว Text และ ProgressBar ที่ถูกส่งมาจาก BackgroundWorker
// Update Progress Number
public string Message
{
set { this.lblProgress.Text = value; }
}
// Update Progress Status
public int ProgressValue
{
set { this.progressStatus.Value = value; }
}
ProgressDlg : เมื่อมีการคลิกที่ Stop บน Dialog ของ ProgressDlg จะส่ง Event ที่เป็น Stop หรือ Cancel ไปยัง frmMain
private void btnStop_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
if (stopProgress != null)
{
stopProgress(sender, e);
}
}
frmMain : โค้ดนี้เมื่อคลิก Start จะทำการเปิดใช้ ProgressDlg และมีการ Handler ในกรณีที่ถูก Stop จาก ProgressDlg
// New BackgroundWorker
bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
// Start the asynchronous operation.
bgWorker.RunWorkerAsync();
// New Dialog
progressDlg = new ProgressDlg();
progressDlg.stopProgress = new EventHandler((s, e1) =>
{
switch (progressDlg.DialogResult)
{
// When click stop button from Progress Dialog
case DialogResult.Cancel:
bgWorker.CancelAsync();
progressDlg.Close();
break;
}
});
progressDlg.ShowDialog();
frmMain : อัพเดดสถานะไปยัง ProgressDlg
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.lblStatus.Text = "Processing...";
// Update status to Dialog
progressDlg.Message = (e.ProgressPercentage.ToString() + "%");
progressDlg.ProgressValue = e.ProgressPercentage;
}
Result Screenshot
ทดสอบการทำงานเปิด frmMain ให้คลิกที่ Start
แสดง Dialog ในไฟล์ ProgressDlg และจะปิดตัวลงเมื่อทำงานครบ 100% หรือสามารถ Stop เพื่อหยุดการทำงานได้
เพิ่มเติม การปิด ControlBox ของ Dialog และไม่ให้ Resize ได้ เพื่อไม่ให้สามารถปิดการทำงานของ Dialog ได้ โดยจะต้องให้คลิกที่ Button : Stop เท่านั้น
ProgressDlg.FormBorderStyle = FormBorderStyle.FixedToolWindow;
ProgressDlg.MaximizeBox = false;
ProgressDlg.MinimizeBox = false;
ใน Form ของ ProgressDlg กำหนดค่า ControlBox : False และ FormBorderStyle : FixedToolWindow
กำหนดค่า MaximizeBox : False และ MinimizeBox : False
หลังจากทดสอบใหม่จะเห็นว่า Control Box จะไม่มีแล้ว และไม่สามารถ Resize ขนาดของ Dialog หรือ Close ได้
เพิ่มเติม ในการใช้งานจริงหลาย ๆ Process จะไม่สามารถทราบถึง Status การทำงานจริงว่าจะจะต้องใช้เวลาเท่าไหร่ จะทราบแค่บาง Process เช่นถ้าเราทราบว่าประมาณ 5 วินาทีก็ให้ทำการปรับแก้ไขในส่วนของ Thread.Sleep ให้มีค่าตัวเลขน้อยลง
for (int i = 1; i <= 100; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(50); // ปรับตัวเลขให้สอดคล้องกับ Loop ที่จะทำงาน
worker.ReportProgress(i);
}
}
ส่วน Process อื่น ๆ อาจจะต้องแทรกการทำงานเป็นระยะ หรือในกรณีที่ไม่ทราบจริง ๆ อาจจะต้องใช้พวก Icon ที่เป็น Loading แทน แล้วชุดคำสั่งในส่วนนี้ก็ให้เอาออกไปเลย แล้วแทรกกการทำงานจริงที่เกิดขึ้น
แทรกการทำงานจริง ๆ โดยไม่่ใช้ Loop
// Call method 1
worker.ReportProgress(20);
// Call method 2
worker.ReportProgress(40);
// Call method 3
worker.ReportProgress(60);
// Call method 4
worker.ReportProgress(80);
// Call method 5
worker.ReportProgress(100);
ทั้งนี้สามาระประยุกต์ใช้กับ Loop For เช่น
for (int i = 1; i <= 100; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
if(i == 0)
{
Call method1();
}else if(i == 20)
{
Call method2();
}
}else if(i == 40)
{
Call method3();
}
}else if(i == 50)
{
Call method4();
}
}else if(i == 80)
{
Call method5();
}
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(50); // ปรับตัวเลขให้สอดคล้องกับ Loop ที่จะทำงาน
worker.ReportProgress(i);
}
}
Code สำหรับ VB.Net
frmMain.vb
Imports System.ComponentModel
Public Class frmMain
Private WithEvents bgWorker As BackgroundWorker
Private ProgressDlg As ProgressDlg
Public Sub New()
' This call is required by the designer.
InitializeComponent()
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
' New BackgroundWorker
bgWorker = New BackgroundWorker
bgWorker.WorkerReportsProgress = True
bgWorker.WorkerSupportsCancellation = True
' Start the asynchronous operation.
bgWorker.RunWorkerAsync()
' New Dialog
ProgressDlg = New ProgressDlg()
AddHandler ProgressDlg.btnStop.Click, AddressOf stopProgress_Click
ProgressDlg.ShowDialog()
End Sub
Private Sub stopProgress_Click(sender As Object, e As EventArgs)
Select Case ProgressDlg.DialogResult
' When click stop button from Progress Dialog
Case DialogResult.Cancel
bgWorker.CancelAsync()
ProgressDlg.Close()
Exit Select
End Select
End Sub
Private Sub bgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgWorker.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
Dim i As Integer
For i = 1 To 100
If (worker.CancellationPending = True) Then
e.Cancel = True
Exit For
Else
' Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(100)
worker.ReportProgress(i)
End If
Next
End Sub
Private Sub bgWorker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgWorker.ProgressChanged
Me.lblStatus.Text = "Processing..."
' Update status to Dialog
ProgressDlg.Message = (e.ProgressPercentage.ToString() + "%")
ProgressDlg.ProgressValue = e.ProgressPercentage
End Sub
Private Sub bgWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted
If e.Cancelled = True Then
Me.lblStatus.Text = "Canceled!"
ElseIf e.Error IsNot Nothing Then
Me.lblStatus.Text = "Error: " & e.Error.Message
Else
Me.lblStatus.Text = "Done!"
End If
progressDlg.Close()
End Sub
End Class
ProgressDlg.vb
Public Class ProgressDlg
' Update Progress Number
Public WriteOnly Property Message() As String
Set(value As String)
Me.lblProgress.Text = value
End Set
End Property
' Update Progress Status
Public WriteOnly Property ProgressValue() As Integer
Set(value As Integer)
Me.progressStatus.Value = value
End Set
End Property
' Stop Event
Public Event stopProgress As EventHandler(Of EventArgs)
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
Me.DialogResult = DialogResult.Cancel
RaiseEvent stopProgress(sender, e)
End Sub
End Class
|
|
|
By : |
TC Admin
|
|
Article : |
บทความเป็นการเขียนโดยสมาชิก หากมีปัญหาเรื่องลิขสิทธิ์ กรุณาแจ้งให้ทาง webmaster ทราบด้วยครับ |
|
Score Rating : |
|
|
Create Date : |
2015-10-14 |
|
Download : |
No files |
|
Sponsored Links |
|
|
|
|
|
|