2013-08-13 5 views
0

프로그램에 진행률 표시 줄이 있으며 각 "DataTable"이 처리 된 후에 값을 추가하려고합니다. 그러나 모든 작업이 완료된 후에 만 ​​업데이트됩니다. 여기 C# 진행률 표시 줄에 진행 상황이 표시되지 않습니다.

코드입니다 :

int c = 0; 
OdbcConnection cn = openOdbcDB(); 
foreach(DataSet ds in allDataSets) 
{ 
    foreach(DataTable dt in ds.Tables) 
    { 
     foreach (DataRow dr in dt.Rows) 
     { 
      insertIntoDatabaseCurrentRecord(dr); 
     } 
    } 
    pbMain.Value = pbMain.Value + (33/totalFiles); 
    c++; 
} 
cn.Close(); 
cn.Dispose(); 

각 테이블이 완료처럼 완료된 후 진행 상황을 보여주기 위해 줄을 강제 할 수있는 방법이 있나요? 현재 루프가 끝나면 진행 상황 만 보입니다. 빈 줄에서 전체 줄로 나옵니다. DataTable 당 약 18000 개의 레코드가 있으므로 모든 레코드를 처리하는 데 약 1 분이 걸리기 때문에 볼 수 있어야합니다.

+1

은 이것에'Thread'를 사용합니다. –

+0

실? 예를 들어 주시겠습니까? – Bojan

+2

또는 Forms 응용 프로그램 인 경우 Application.DoEvents(). (빠른 & 더러운) –

답변

1

사용 BackgroundWorker에 :

4

이 모든 것이 UI 스레드에서 발생한다고 가정하면 루프 처리로 스레드를 바쁘게 유지하기 때문에 업데이트하지 않을 것입니다. UI 스레드가 멈추지 않도록 처리하려면 백그라운드 스레드를 생성해야합니다. 그런 다음 Contol.Invoke을 사용하여 진행률 막대를 UI 스레드로 다시 밀어 넣는 부분을 실제로 설정해야합니다.

여기를 참조하십시오. http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx 스레딩 예제 (이 방법은 여러 가지가 있지만)와 Control.Invoke입니다.

int c = 0; 
OdbcConnection cn = openOdbcDB(); 
foreach(DataSet ds in allDataSets) 
{ 
    foreach(DataTable dt in ds.Tables) 
    { 
     foreach (DataRow dr in dt.Rows) 
     { 
      insertIntoDatabaseCurrentRecord(dr); 
      Application.DoEvents(); //Quick and dirty 
     } 
    } 
    pbMain.Value = pbMain.Value + (33/totalFiles); 
    c++; 
} 
cn.Close(); 
cn.Dispose(); 
0

당신의 루프가 활성 스레드를 차단하고 있기 때문에, 다른 스레드 (깨끗한 방법)를 사용하는 것 또는 단순히는 윈폼에 Application.DoEvents()를 사용

BackgroundWorker _worker; 

// executes on another thread 
void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    BackgroundWorker worker = (BackgroundWorker)sender; 

    int c = 0; 
    OdbcConnection cn = openOdbcDB(); 
    foreach (DataSet ds in allDataSets) 
    { 
     foreach (DataTable dt in ds.Tables) 
     { 
      foreach (DataRow dr in dt.Rows) 
      { 
       insertIntoDatabaseCurrentRecord(dr); 
      } 
     } 
     // do not update UI elements here, but in ProgressChanged event 
     //pbMain.Value = pbMain.Value + (33/totalFiles); 
     c++; 

     worker.ReportProgress(c); // call ProgressChanged event of the worker and pass a value you can calculate the percentage from (I choose c, since it is the only calculated value here) 
    } 
    cn.Close(); 
    cn.Dispose(); 
} 

// gets called on your main thread 
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // update the progressbar here. 
    // e.ProgressPercentage holds the value passed in DoWork. 
} 
+2

어. 백그라운드 스레드를 사용하고'Application.DoEvents'를 사용하지 마십시오. –

+0

''pbMain.Refresh()'충분하다고 생각하십니까? –

+2

@MattBurland 나는 당신과 동의하지만, 그가 단지 DoEvents()를 사용할 수 있지만 빠른 결과를보고 싶다면 반드시 스레드를보아야합니다. –

관련 문제