2012-10-21 2 views
1

저는 C#에 익숙하지 않으며 객체 지향 프로그래밍에 대한 내 마음을 감싸줍니다. 다음은 내가 성취하고자하는 작업입니다.BackgroundWorker ProgressChanged가 별도의 클래스에서 트리거되는 양식

Form1과 연결된 별도의 클래스 인 connect (동일한 네임 스페이스)가있는 Windows Form 응용 프로그램이 있습니다.

오랜 시간 동안 코드를 실행할 때 배경 작업자를 사용하는 것이 좋습니다 (UI가 정지되지 않도록). 그래서 Form1에 백그라운드 작업자를 만들고 progresschanged 핸들을 만들었습니다. 별도의 연결 클래스에서 progresschange를 트리거하는 방법을 찾으려고합니다. Form1의 progresschange 블록에는 어떤 텍스트가 화면에 표시되는지 결정하는 case/switch가 있습니다.

가장 좋은 방법은 무엇입니까? 배경 수업을 다른 수업에 전달해야합니까?

+0

왜 연결 클래스에서 progress_changed를 처리 하시겠습니까? –

+0

connect class는 SQL 서버에 연결하거나 쿼리를 실행하는 것과 같은 두 가지를 통해 실행됩니다. 나는 결국 현재 상태를 반영하기 위해 form1의 statusstrip 레이블을 변경할 수 있기를 원한다. (서버 연결, 쿼리 실행 등). 연결 클래스에서 form1의 statusstrip 레이블을 UI를 잠그지 않는 또 다른 메서드로 업데이트 할 수 있다면 나는 그 것이다. –

답변

2

연결 클래스의 단계를 다른 메소드로 분해하고 아래와 같이 순차적으로 호출 할 수 있습니다. 연결 클래스 객체에서 progresschanged 이벤트를 트리거하지 않아도됩니다.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ConnectClass conObject= new ConnectClass(); 
    backgroundWorker.ReportProgress(30, "Connecting ..."); 
    conObject.Connect(); 
    backgroundWorker.ReportProgress(30, "Connected."+"\n Executing query"); 
    conObject.Execute(); 
    backgroundWorker.ReportProgress(40, "Execution completed."); 
} 
+0

ReportProgress int 매개 변수는 매번 다른 값을 사용해야합니까? 첫 번째와 두 번째가 같은 int를 가지고있는 것을 보았습니다 - 배경 노동자는 방금 다시 호출되었으므로 변경이 있다는 것을 인식합니까? –

+0

int는 완료되는 작업의 백분율을 나타냅니다. 모든 타크는 최대 100 개까지 추가해야합니다. 그리고 progresschanged 이벤트는 ReportProgress 호출에 의해 트리거됩니다. progress_changed 이벤트에서 ReportProgress 호출을 통해 전달 된 메시지를 캡처하고 업데이트해야합니다 메시지 상태 표시 줄에 따라 –

+0

좋은 소리 - 고마워요! –

5

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

+0

감사합니다. 나는 이것도 잘 살펴볼 것이다. –

관련 문제