2009-07-28 2 views
9

저는 C#과 WPF에서 일하고 있는데, 매우 새로운 것입니다.통화 중 루프 동안 진행 상황을 표시하려면 어떻게합니까?

외부 소스에서 많은 양의 데이터를 읽는 루프가 있습니다. 이 프로세스는 약 20 초 정도 소요되며 진행 상황을 사용자에게 보여주고 싶습니다. 멋진 진행 막대가 필요하지 않으므로 "단계 1/1000"이라고 말한 레이블에 내 진행 상황을 표시하고 "단계 2/1000"등으로 변경했습니다.

내 코드는 다음과 유사합니다. 이 :

그러나 분석 중에는 화면이 멈추고 진행이 진행되는 것으로 표시되지 않습니다. C++의 과거에서 이러한 동작을 이해할 수 있습니다. 루프에서 알림을받는 진행률 표시 줄이나 다시 그리기/새로 고침 또는 Windows/응용 프로그램에서 메시지 대기열을 처리하도록하는 별도의 스레드가있을 수 있습니다.

C#에서 올바른 방법은 무엇입니까? 내가 라벨에 묶여 아니에요, 그렇게 간단한 진행 바 팝업 화면이 있다면 나는 BackgroundWorker에 작업을 이동 ... 그것도 좋은 것이 라벨 대신

감사

+0

이 당신을 위해 도움이 될 수 있습니다 .. 나는 또한 익명 메소드를 추가하고 .. 당신이 생각하지 않았 으면 다소 분석하여 문자열을 해결하기 위해 자유를했다 다른 DispatcherPriority 옵션을

PS를 시도 할 수 있습니다 , ** 100 % Tested ** ** http://stackoverflow.com/a/42995210/6863414 –

답변

11

를 사용할 수 있으며, ReportProgress 방법을 사용하십시오.

for (i = 0; i < count; i++) 
{ 
    ... do analysis ... 
    worker.ReportProgress((100 * i)/count); 
} 

private void MyWorker_ProgressChanged(object sender, 
    ProgressChangedEventArgs e) 
{ 
    taskProgressBar.Value = Math.Min(e.ProgressPercentage, 100); 
} 
+0

스레드로부터 안전합니까? –

+1

예, 그래야합니다. 백그라운드 작업자는 하나의 스레드에만 있고 진행률 막대 업데이트는 UI 스레드에만 있습니다. UI 스레드 이외의 스레드는 값을 업데이트하려고 시도하면 예외를 throw합니다. 따라서이 메서드로 스레드 안전성을 보장 할 수 있습니다. – user7116

2

현재 스레드가 궁극적으로 레이블을 설정하는 UI 스레드보다 우선 순위가 높기 때문에 UI가 업데이트되지 않습니다. 따라서 스레드가 작업을 마칠 때까지 라벨이 업데이트됩니다. 우리

행운이있다 백그라운드에서

labelProgress.Dispatcher.Invoke(DispatcherPriority.Background, 
        () => labelProgress.Content = string.Format("Step {0}{1}", i, countLabel)); 

이 화재 최대 스레드 ... 다른 우선 순위로 새 스레드를 발사 할 수있는 모든 WPF 컨트롤에 디스패처 재산이며 작업을 얻을 것입니다 끝난! 또한

3
//Create a Delegate to update your status button 
    delegate void StringParameterDelegate(string value); 
    String countLabel = "/" + count.ToString(); 
    //When your button is clicked to process the loops, start a thread for process the loops 
    public void StartProcessingButtonClick(object sender, EventArgs e) 
    { 
     Thread queryRunningThread = new Thread(new ThreadStart(ProcessLoop)); 
     queryRunningThread.Name = "ProcessLoop"; 
     queryRunningThread.IsBackground = true; 
     queryRunningThread.Start(); 
    } 

    private void ProcessLoop() 
    { 
     for (i = 0; i < count; i++) 
     { 
      ... do analysis ... 
      UpdateProgressLabel("Step "+i.ToString()+countLabel); 
     } 
    } 

    void UpdateProgressLabel(string value) 
    { 
     if (InvokeRequired) 
     { 
      // We're not in the UI thread, so we need to call BeginInvoke 
      BeginInvoke(new StringParameterDelegate(UpdateProgressLabel), new object[] { value }); 
      return; 
     } 
     // Must be on the UI thread if we've got this far 
     labelProgress.Content = value; 
    } 
+0

BackgroundWorker가 제공되어 스레드에서 발생하는 모든 혼란을 처리 할 필요가 없습니다. – user7116

+0

@sixlettervariables이 메서드의 값은 정수를 호출자에게 전달하는 것보다 유연성을 제공한다는 것입니다. 아무 것도 할 수 있습니다 (예 : 상태 메시지 전달). – ean5533

관련 문제