장시간(3초 이상)의 작업이 진행되는 경우 사용자가 멍하니 아무런 변화가 없는 모니터를 보게 하는 것 보다 작업 진행 상태를 보여주는 것이 좋습니다. 퍼센트로 작업 진행률을 보여주면 더할 나위 없이 좋겠지만 그렇지 못할 경우에는 진행 애니메이션이라도 보여주는 것이 좋습니다.
이렇게 작업 애니메이션을 보여주기 위해서 C#에서는 BackgroundWorker를 많이 사용합니다.
사용자에게 보여지는 화면은 Main Thread에서 생성하고 실제 작업은 BackgroundWorker에서 담당하게 됩니다. 작업이 진행되는 동안 이벤트를 받아 UI에서 진행률을 업데이트할 수 있습니다.
- DoWork : 실제 작업을 담당하는 이벤트
- ProgressChanged : 작업 진행률을 업데이트하는 이벤트
- RunWorkerCompleted : 작업이 끝났을 때 호출되는 이벤트
BackgroundWorker에 대한 예제는 MSDN에서 찾을 수 있습니다.
이렇게 개발을 진행해도 되지만 개발의 편의성을 위해 BackgroundWorker와 UI를 감싸는 클래스를 만들어 보았습니다.
이 클래스는 작업이 진행되는 동안에 부모 윈도우에 작업 애니메이션을 보여주고 작업이 끝나면 애니메이션을 멈추게 됩니다. 작업은 가상 함수를 override해서 수행할 수 있습니다.
작업 애니메이션은 Telerik의 RadWaitingBar를 이용하여 구현하였습니다.(GIF 애니메이션 파일을 따로 구할 필요가 없어 편리합니다.)
- class ARSWorker
- {
- protected System.Windows.Forms.Control _parent = null;
- private BackgroundWorker worker = new BackgroundWorker() { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
- private RadWaitingBar waiting = null;
- public ARSWorker(System.Windows.Forms.Control control = null)
- {
- this._parent = control;
- }
- public virtual void StartWork()
- {
- if (_parent != null)
- {
- waiting = new RadWaitingBar()
- {
- Size = new System.Drawing.Size(200, 200),
- WaitingStyle = Telerik.WinControls.Enumerations.WaitingBarStyles.DotsSpinner,
- BackColor = System.Drawing.Color.Transparent, /// 배경을 투명하게 처리
- Parent = _parent
- };
- waiting.Location = new System.Drawing.Point(_parent.Location.X + (_parent.Width - waiting.Width) / 2,
- _parent.Location.Y + (_parent.Height - waiting.Height) / 2); /// 부모의 가운데로 위치를 맞춤
- _parent.Controls.Add(waiting);
- }
- worker.DoWork += Worker_DoWork;
- worker.ProgressChanged += Worker_ProgressChanged;
- worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
- if (worker.IsBusy != true)
- {
- this.waiting.StartWaiting(); /// 작업 애니메이션 시작
- worker.RunWorkerAsync();
- }
- }
- public void CancelWork()
- {
- this.worker.CancelAsync();
- }
- private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
- {
- this.UpdateProgress(e.ProgressPercentage);
- }
- private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- if (this.waiting != null)
- {
- this.waiting.StopWaiting(); /// 작업이 끝나면 애미메이션도 멈춤
- if (this._parent != null) this._parent.Controls.Remove(this.waiting);
- this.waiting.Dispose();
- }
- this.WorkCompleted();
- }
- private void Worker_DoWork(object sender, DoWorkEventArgs e)
- {
- this.DoWork(sender as BackgroundWorker);
- }
- protected virtual void DoWork(System.ComponentModel.BackgroundWorker worker) { throw new NotImplementedException(); }
- protected virtual void UpdateProgress(int precent) { }
- protected virtual void WorkCompleted() { }
- }
이 클래스를 상속해서 DoWork, UpdateProgress, WorkCompleted를 override하고 StartWork 함수로 작업을 시작하면 됩니다.
화면 가운데 작업 애니메이션이 있는 것을 확인할 수 있습니다.
감사합니다
답글삭제C#을 배우는중입니다
너무 유용하게 사용하겠습니다~~^^