ConnectWork 클래스에 BackgroundWorker를 배치 할 수도 있습니다. 그런 다음이 클래스에서 이벤트를 작성하여 진행 상황과 완료를 호출 양식으로 다시보고 할 수 있습니다.
using System;
using System.ComponentModel;
namespace WindowsTest
{
public class Connect
{
BackgroundWorker bw;
public Connect()
{
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork +=new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
}
public delegate void ProgressChangedHandler(Object sender, ProgressChangedEventArgs e);
public event ProgressChangedEventHandler ProgressChanged;
protected void RaiseProgressChangedEvent(ProgressChangedEventArgs e)
{
if (ProgressChanged == null)
{
return;
}
ProgressChanged(this, e);
}
public delegate void WorkCompleteEventHandler(Object sender, RunWorkerCompletedEventArgs e);
public event WorkCompleteEventHandler WorkComplete;
protected void RaiseWorkCompleteEvent(RunWorkerCompletedEventArgs e)
{
if (WorkComplete == null)
{
return;
}
WorkComplete(this, e);
}
public void Cancel()
{
if (bw.IsBusy)
{
bw.CancelAsync();
}
}
public void BeginLongRunningProcess()
{
bw.RunWorkerAsync();
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RaiseWorkCompleteEvent(e);
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
RaiseProgressChangedEvent(e);
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (ConnectToServer())
{
bw.ReportProgress(0, "Connected to server");
e.Result = LongRunningProcess();
if (e.Result.ToString() == "Cancelled")
{
e.Cancel = true;
return;
}
}
else
{
//Connection failed
e.Cancel = true;
}
}
private bool ConnectToServer()
{
//Attempt connection
return true;
}
private string LongRunningProcess()
{
int recordCount = 250;
for (int i = 0; i <= recordCount; i++)
{
if (bw.CancellationPending)
{
return "Cancelled";
}
double progress = ((double)i/(double)recordCount) * 100;
bw.ReportProgress((int)progress , "Running Process");
System.Threading.Thread.Sleep(25);
}
return "The result is 2";
}
}
}
그런 다음 양식에서 이벤트를 처리하기 만하면됩니다.
namespace WindowsTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Connect connect;
private void btnConnect_Click(object sender, EventArgs e)
{
connect = new Connect();
connect.ProgressChanged += new ProgressChangedEventHandler(connect_ProgressChanged);
connect.WorkComplete += new Connect.WorkCompleteEventHandler(connect_WorkComplete);
connect.BeginLongRunningProcess();
}
private void connect_WorkComplete(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
lblStatus.ForeColor = Color.Red;
lblStatus.Text = string.Format("Status: {0}", "User Cancelled!");
return;
}
if (e.Error != null)
{
//Process exception
lblStatus.Text = string.Format("Status: {0}", "Error!");
lblStatus.ForeColor = Color.Red;
return;
}
lblStatus.Text = string.Format("Status: Complete. {0}", e.Result);
}
private void connect_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = string.Format("Status: {0}", e.UserState.ToString());
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (connect != null)
{
connect.Cancel();
}
}
}
}
BackgroundWorker.ReportProgress() 메서드의 두 번째 매개 변수 (UserState)는 모든 개체를 전달할 수 있습니다. 문자열 일 필요는 없습니다. 예를 들어 데이터베이스에서 행/행을 검색 한 경우이 메서드를 통해 행을 다시 사용자 인터페이스로 전달할 수 있습니다. BackgroundWorker.DoWork 메서드의 e.Result도 마찬가지입니다.
Eric
왜 연결 클래스에서 progress_changed를 처리 하시겠습니까? –
connect class는 SQL 서버에 연결하거나 쿼리를 실행하는 것과 같은 두 가지를 통해 실행됩니다. 나는 결국 현재 상태를 반영하기 위해 form1의 statusstrip 레이블을 변경할 수 있기를 원한다. (서버 연결, 쿼리 실행 등). 연결 클래스에서 form1의 statusstrip 레이블을 UI를 잠그지 않는 또 다른 메서드로 업데이트 할 수 있다면 나는 그 것이다. –