|
C# การใช้ workerProgressbar แบบบ้านๆ |
หลังจากที่ได้ลองใช้ backgroundworker กับ progressbar ตามบทความนี้
https://www.thaicreate.com/community/cs-vb-net-backgroundworker.html
https://www.thaicreate.com/community/progressbar-dialog-backgroundworkger.html
ผมได้ พบว่า backgroundworker กับ progressbar ยังไม่ตอบโจทย์เท่าไหร่ครับ
เพราะว่าตัว backgroundworker เอง ให้ ProgressPercentage แบบ Int
ซึ่งค่อนข้างดูความแตกต่างยากถ้าหากรันงานทีละเยอะๆ
ผมจึงได้นำ backgroundworker มายำเพื่อให้ได้ ProgressPercentage แบบ double
ไหนๆก็จะยำแล้ว จึงนำเอา progressbar มาใช้งานด้วยซะเลย
ซึ่งจะได้โค้ดตามนี้ครับ
Code (C#)
public class _ProgressChangedEventArgs : EventArgs
{
private readonly double progressPercentage;
private readonly object userState;
public _ProgressChangedEventArgs(double progressPercentage, object userState)
{
this.progressPercentage = progressPercentage;
this.userState = userState;
}
public double ProgressPercentage
{
get { return progressPercentage; }
}
public object UserState
{
get { return userState; }
}
}
public delegate void _ProgressChangedEventHandler(object sender, _ProgressChangedEventArgs e);
[DefaultEvent("DoWork")]
public class WorkerProgressbar : System.Windows.Forms.ProgressBar
{
// Private statics
private static readonly object doWorkKey = new object();
private static readonly object runWorkerCompletedKey = new object();
private static readonly object progressChangedKey = new object();
// Private instance members
private bool canCancelWorker = false;
private bool workerReportsProgress = false;
private bool cancellationPending = false;
private bool isRunning = false;
private AsyncOperation asyncOperation = null;
private readonly WorkerThreadStartDelegate threadStart;
private readonly SendOrPostCallback operationCompleted;
private readonly SendOrPostCallback progressReporter;
public WorkerProgressbar()
{
threadStart = new WorkerThreadStartDelegate(WorkerThreadStart);
operationCompleted = new SendOrPostCallback(AsyncOperationCompleted);
progressReporter = new SendOrPostCallback(ProgressReporter);
}
private void AsyncOperationCompleted(object arg)
{
isRunning = false;
cancellationPending = false;
OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg);
}
[Browsable(false)]
public bool CancellationPending
{
get { return cancellationPending; }
}
public void CancelAsync()
{
if (!WorkerSupportsCancellation)
{
throw new InvalidOperationException("BackgroundWorker_WorkerDoesntSupportCancellation");
}
cancellationPending = true;
}
public event DoWorkEventHandler DoWork
{
add
{
this.Events.AddHandler(doWorkKey, value);
}
remove
{
this.Events.RemoveHandler(doWorkKey, value);
}
}
/// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.IsBusy"]/*' />
[Browsable(false)]
public bool IsBusy
{
get
{
return isRunning;
}
}
/// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.OnDoWork"]/*' />
protected virtual void OnDoWork(DoWorkEventArgs e)
{
DoWorkEventHandler handler = (DoWorkEventHandler)(Events[doWorkKey]);
if (handler != null)
{
handler(this, e);
}
}
/// <include file='doc\BackgroundWorker.uex' path='docs/doc[@for="BackgroundWorker.OnRunWorkerCompleted"]/*' />
protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
{
RunWorkerCompletedEventHandler handler = (RunWorkerCompletedEventHandler)(Events[runWorkerCompletedKey]);
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnProgressChanged(_ProgressChangedEventArgs e)
{
_ProgressChangedEventHandler handler = (_ProgressChangedEventHandler)(Events[progressChangedKey]);
if (handler != null)
{
handler(this, e);
}
}
public event _ProgressChangedEventHandler ProgressChanged
{
add
{
this.Events.AddHandler(progressChangedKey, value);
}
remove
{
this.Events.RemoveHandler(progressChangedKey, value);
}
}
// Gets invoked through the AsyncOperation on the proper thread.
private void ProgressReporter(object arg)
{
OnProgressChanged((_ProgressChangedEventArgs)arg);
}
// Cause progress update to be posted through current AsyncOperation.
public void ReportProgress(double percentProgress)
{
ReportProgress(percentProgress, null);
}
// Cause progress update to be posted through current AsyncOperation.
public void ReportProgress(double percentProgress, object userState)
{
if (!WorkerReportsProgress)
{
throw new InvalidOperationException("BackgroundWorker_WorkerDoesntReportProgress");
}
// System.Windows.Forms.MessageBox.Show("" + percentProgress);
_ProgressChangedEventArgs args = new _ProgressChangedEventArgs(percentProgress, userState);
if (asyncOperation != null)
{
asyncOperation.Post(progressReporter, args);
}
else
{
progressReporter(args);
}
}
public void RunWorkerAsync()
{
RunWorkerAsync(null);
}
public void RunWorkerAsync(object argument)
{
if (isRunning)
{
throw new InvalidOperationException("BackgroundWorker_WorkerAlreadyRunning");
}
isRunning = true;
cancellationPending = false;
asyncOperation = AsyncOperationManager.CreateOperation(null);
threadStart.BeginInvoke(argument,
null,
null);
}
public event RunWorkerCompletedEventHandler RunWorkerCompleted
{
add
{
this.Events.AddHandler(runWorkerCompletedKey, value);
}
remove
{
this.Events.RemoveHandler(runWorkerCompletedKey, value);
}
}
[DefaultValue(false)]
public bool WorkerReportsProgress
{
get { return workerReportsProgress; }
set { workerReportsProgress = value; }
}
[DefaultValue(false)]
public bool WorkerSupportsCancellation
{
get { return canCancelWorker; }
set { canCancelWorker = value; }
}
private delegate void WorkerThreadStartDelegate(object argument);
private void WorkerThreadStart(object argument)
{
object workerResult = null;
Exception error = null;
bool cancelled = false;
try
{
DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(argument);
OnDoWork(doWorkArgs);
if (doWorkArgs.Cancel)
{
cancelled = true;
}
else
{
workerResult = doWorkArgs.Result;
}
}
catch (Exception exception)
{
error = exception;
}
RunWorkerCompletedEventArgs e =
new RunWorkerCompletedEventArgs(workerResult, error, cancelled);
asyncOperation.PostOperationCompleted(operationCompleted, e);
}
}
ส่วนโค้ดในหน้า ฟอร์ม ก็จะคล้ายๆกับ backgroundworker คือ มี
DoWork ProgressChanged RunWorkerCompleted
ดังนี้
Code (C#)
int i;
private void workerProgressbar1_DoWork(object sender, DoWorkEventArgs e)
{
for (i = 1; i <= workerProgressbar1.Maximum; i++)
{
if (workerProgressbar1.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(50);
workerProgressbar1.ReportProgress((double)i * (double)100 / (double)workerProgressbar1.Maximum);
}
}
}
private void workerProgressbar1_ProgressChanged(object sender, TestControl.Control._ProgressChangedEventArgs e)
{
workerProgressbar1.Value = i;
this.Text = (e.ProgressPercentage.ToString("0.00000") + "%");
}
private void workerProgressbar1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
this.Text = "Canceled!";
}
else if (e.Error != null)
{
this.Text = "Error: " + e.Error.Message;
}
else
{
this.Text = "Done!";
}
MessageBox.Show("Working Finished.");
}
private void button1_Click(object sender, EventArgs e)
{
workerProgressbar1.Maximum = 10000;
workerProgressbar1.WorkerReportsProgress = true;
workerProgressbar1.WorkerSupportsCancellation = true;
workerProgressbar1.RunWorkerAsync();
}
ผลที่ได้ก็ประมาณนี้
ถึงแม้ตามความคิดผม นี่ก็ยังไม่ตอบโจทย์ซักเท่าไหร่
เพราะว่ายังถือว่าใช้ยากอยู่ หากเราจะเอาไปแทน โค้ดต่างๆ อย่างการเรียกใช้ database หรือการโหลดข้อมูลต่างๆ
เพราะต้องเพิ่มตั้ง 3 event เพื่อให้ได้แค่งานเดียว
แต่ก็ยังถือว่าเป็นการเริ่มต้นของการพัฒนาได้เช่นกันครับ
|
|
|
|
|
|
|
|
By : |
TOR_CHEMISTRY
|
|
Article : |
บทความเป็นการเขียนโดยสมาชิก หากมีปัญหาเรื่องลิขสิทธิ์ กรุณาแจ้งให้ทาง webmaster ทราบด้วยครับ |
|
Score Rating : |
|
|
Create Date : |
2017-04-28 |
|
Download : |
No files |
|
Sponsored Links |
|
|
|
|
|
|