namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
BackgroundWorker bgWorker;
Action<int> myProgressReporter;
public Window1()
{
InitializeComponent();
bgWorker = new BackgroundWorker();
bgWorker.DoWork += bgWorker_Task;
bgWorker.RunWorkerCompleted += myWorker_RunWorkerCompleted;
// hook event to method
bgWorker.ProgressChanged += bgWorker_ReportProgress;
// hook the delegate to the method
myProgressReporter = updateProgress;
bgWorker.WorkerReportsProgress = true;
}
private void myWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
object result;
result = e.Result;
MessageBox.Show(result.ToString());
progressBar1.Value = 0;
button1.IsEnabled = true;
}
private void bgWorker_ReportProgress(object sender, ProgressChangedEventArgs e)
{
System.Windows.Threading.Dispatcher disp = button1.Dispatcher;
disp.BeginInvoke(myProgressReporter,e.ProgressPercentage);
//Dispatcher.BeginInvoke(myProgressReporter, DispatcherPriority.Normal, e.ProgressPercentage);
}
private void updateProgress(int progressPercentage)
{
progressBar1.Value = progressPercentage;
}
private void bgWorker_Task(Object sender, DoWorkEventArgs e)
{
int total = 1000;
for (int i = 1; i <= total; i++)
{
if (bgWorker.WorkerReportsProgress)
{
int p = (int)(((float)i/(float)total) * 100);
bgWorker.ReportProgress(p);
}
Thread.Sleep(1); // Without Thread.Sleep(x) the main thread freezes or gives stackoverflow exception,
}
e.Result = "Completed";
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if(!bgWorker.IsBusy)
bgWorker.RunWorkerAsync("This is a background process");
button1.IsEnabled = false;
}
}
}
답변
귀하의 (인공적인) 시나리오에서 1000 스레드 요청을 메인 스레드로 보내주기 때문에
유휴 루프를 수행 할 시간이 없습니다 (화면 업데이트를 수행하는 데 필요함).
(TerrorAustralis 덕택에) bgWorker_ReportProgress 및 myProgressReporter 메소드를 병합해야합니다. 이제 stackoverflow의 가능한 원인 인 두 번을 동기화합니다. 의 UpdateProgress 이벤트를 파견하는 것은 BackgroundWorker에의 주요 특징 중 하나입니다
이private void bgWorker_ReportProgress(object sender, ProgressChangedEventArgs e)
{
//System.Windows.Threading.Dispatcher disp = button1.Dispatcher;
//disp.BeginInvoke(myProgressReporter,e.ProgressPercentage);
progressBar1.Value = progressPercentage; // safe because we're on the main Thread here
}
실제 작업을하거나 루프에서 일부 IO를 수행하면 progressbar가 잘 업데이트됩니다. 메소드를 병합하지 않아도되지만 병합하지 않아도 차이는 없습니다. – Syler
맞습니다. 매우 빡빡한 업데이트 루프가 문제였습니다. 실제 상황에서는 다음을 고려하십시오 :'(p % 10 == 0) bgWorker.ReportProgress (p);', 총 10 - 100 건의 업데이트를 목표로합니다. –
있는 posibility :
Dispatcher.BeginInvoke()가 비동기 작업입니다. 이 경우 작업이 완료되기 전에 다시 시도 할 수 있습니다. 이것이 문제인지 확인하려면, 동기 인 Dispatcher.Invoke()를 시도하십시오.
가능한 해결 방법은 진행률 막대를 업데이트하기 만하면 backgroundWorker ProgressChanged 이벤트가 명시 적 디스패처를 사용하지 않고이 작업을 수행 할 수 있습니다. .
예, 좋은 캐치, 나는 그것을 놓쳤습니다. 내 대답을 편집 할 것입니다. –
- 1. Thread.Sleep이 장기간 동안 정확하지 않은 이유는 무엇입니까?
- 2. Dispatcher.BeginInvoke (...)가 WPF의 UI 컨트롤을 어떻게 업데이트합니까?
- 3. WPF의 코드로 UI 업데이트
- 4. WPF 컨트롤을 "실시간"으로 업데이트하기
- 5. lock (this) thread.sleep이 ASP.NET 스레딩에서 작동하지 않는 이유는 무엇입니까?
- 6. WinForms에서 다른 스레드에서 UI 컨트롤을 업데이트 할 수없는 이유는 무엇입니까?
- 7. UI를 업데이트하기 전에 viewDidLoad가 대기하는 이유는 무엇입니까?
- 8. 거북이 SVN이 필요한 이유는 무엇입니까?
- 9. 디자이너가 Winform에서 System.ComponentModel.ISupportInitialize가 필요한 이유는 무엇입니까?
- 10. 번호 접미사가 필요한 이유는 무엇입니까?
- 11. 전달 선언이 필요한 이유는 무엇입니까?
- 12. PhotoCamera에 VideoBrush가 필요한 이유는 무엇입니까?
- 13. 콜백 이벤트가 필요한 이유는 무엇입니까?
- 14. 웹에 HTTP가 필요한 이유는 무엇입니까?
- 15. 여기에 UseCompatibleTextRendering이 필요한 이유는 무엇입니까?
- 16. ": nodoc :"구문이 필요한 이유는 무엇입니까?
- 17. Android - 올바르게 위젯과 컨트롤을 참조 및 업데이트하기
- 18. BackgroundWorker에서 개체 반환
- 19. 사용자가 WPF의 UI 컨트롤에 주석을 추가하는 것을 허용하는 방법은 무엇입니까?
- 20. SQLite 데이터베이스의 값을 업데이트하기 위해 어떤 호출을해야합니까?
- 21. 인 메모리 데이터베이스가 필요한 이유는 무엇입니까?
- 22. IMPLEMENT_DYNAMIC에 빈 생성자가 필요한 이유는 무엇입니까?
- 23. WPF의 조건에 따라 다른 컨트롤을 표시하는 방법은 무엇입니까?
- 24. HTTP 클라이언트에서 InputStream이 필요한 이유는 무엇입니까? (자바)
- 25. BackGroundWorker에서 textBox.Text를 읽으십시오.
- 26. Ruby Enumerator - 예외 처리가 필요한 이유는 무엇입니까?
- 27. UI 요소에서 항상 UI 요소를 생성/업데이트해야하는 이유는 무엇입니까?
- 28. RedirectStandardOutput에 필요한 ANSI 코드가없는 이유는 무엇입니까?
- 29. BackgroundWorker에서 컨트롤의 속성 변경 C#
- 30. WPF의 기존 컨트롤을 복사하여 컨트롤을 동적으로 추가하는 모범 사례
궁금한 점 : TerrorAustralis의 조언을 따르고 ReportProgress를 동기식으로 수행하는 경우 여전히 절전 모드가 필요합니까? 일종의 내부 최적화일지도 모릅니다. 모든 비동기 호출이 차단 된 후에 실행됩니다. –