2013-12-17 2 views
0

을 참조하십시오 http://codepaste.net/djw3cw를 코드비동기/기다리고 있습니다 - 윈폼 버전

것이 사실이라면/곧 Linq에 같이 될 것입니다 비동기 프로그래밍 기다리고 비동기, 내 생각이 질문이 아닌 사소한 확장이다 Async/Await with a WinForms ProgressBar

코드가 최적이지만 코드 대신 단어로 포인터 나 답변을 쓸 때 유용합니다.

문제는 asynch/await를 사용하여 진행률 표시 줄을 설정하는 방법입니다. 과거에는 Dispatcher를 성공적으로 사용했습니다. 여기

Please see: http://codepaste.net/djw3cw for the code 
What is done: a textbox has any text in it converted to an int, then when 
"mybutton1" is clicked, work is done based on the int, for int ms (int = 
milliseconds). 
During this time, a progressbar "myProgressBar" is shown for 
every tenth-percent step 
When work is complete, the label/textblock controls are updated 
But the below does not work right: the form simply freezes until the work is 
complete. How to fix it? 
How to do this using Task-based Asynchronous Pattern (TAP) or Async/Await, 
rather than a Dispatcher? 

문제의 코드 자명 한 조각이다.

private void mybutton1_Click(object sender, RoutedEventArgs e) 
    { 
     myLabel.Content = myTextBox.Text; 

     string myString = myTextBox.Text; 

     bool result = Int32.TryParse(myString, out myInteger); 

     if (result == true) 
     { 
     myTextblock.Text = "Success, thread will be delayed by: " + myInteger.ToString() + " ms"; 

      // 
      int CounterInteger = 0; 
      for (int j = 0; j < myInteger; j++) // set # itt 
      { 

       Thread.Sleep(1); //do some work here 

       // myClassDoWork1.Delay_DoWork(myInteger); //optional way to do work in another class... 

       if (j % (myInteger/10) == 0) //display progress bar in 10% increments 
       { 

        CounterInteger = CounterInteger + 10; 
        myProgressBar.Value = (double)CounterInteger; // won't work here in a parallel manner...must use Dispatcher.BeginInvoke Action 
        //how to make this work using Async/Await? see: https://stackoverflow.com/questions/17972268/async-await-with-a-winforms-progressbar 

       } 

      } 
      /// 
      /// // above does not work properly: the form simply freezes until the work is complete. How to fix it? 
      /// 


      myLabel.Content = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds"; 
      myTextblock.Text = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds"; 
      return; 
     } 
     else 
     { 
      myTextblock.Text = "Error, integer not entered, try again." + myTextBox.Text; 
      myLabel.Content = "Error, integer not entered, try again."; 
      return; 
     } 


    } 
+0

코드를 편집하여 문제를 완벽하게 보여주고 가능한 한 짧게 편집하는 것이 가장 이상적입니다. –

+0

안녕하세요 존 - 사실이 주제 "C# In Depth"에 대한 책을 읽고 있습니다. CodePaste에서 코드를 확인합니까? 여기서 잘라내어 붙여 넣는 코드가 나에게 잘 맞지 않는다는 것을 알았습니다. 미안합니다. – PaulDecember

+1

예, CodePaste에서 코드를 볼 수 있습니다. 그러나 이는 단순히 질문하는 좋은 방법이 아닙니다. 스택 오버 플로우 마크 다운 편집기 (및 미리보기 창)에 익숙해 질 필요가 있습니다 - 질문을 명확하게 형식화하고 (단지 오프 사이트 코드에 링크하는 것이 아니라) 좋은 질문을 만드는 것이 중요합니다. –

답변

5

당신은 당신의 코드에서 어떤 async 또는 await이 없습니다. UI 스레드가 블로킹하는 이유는 동기식 코드를 실행하고 있기 때문입니다.

백그라운드 스레드로 푸시하려는 CPU 바인딩 코드가있는 경우 Task.Run을 사용하십시오. 그러면 UI 스레드의 코드 await을 사용할 수 있습니다.

private async void mybutton1_Click(object sender, RoutedEventArgs e) 
{ 
    myLabel.Content = myTextBox.Text; 
    string myString = myTextBox.Text; 
    bool result = Int32.TryParse(myString, out myInteger); 

    if (result == true) 
    { 
    myTextblock.Text = "Success, thread will be delayed by: " + myInteger.ToString() + " ms"; 
    IProgress<int> progress = new Progress<int>(value => { myProgressBar.Value = value; }); 
    await Task.Run(() => 
    { 
     int CounterInteger = 0; 
     for (int j = 0; j < myInteger; j++) 
     { 
     Thread.Sleep(1); 
     if (j % (myInteger/10) == 0) 
     { 
      CounterInteger = CounterInteger + 10; 
      progress.Report(CounterInteger); 
     } 
     } 
    } 

    myLabel.Content = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds"; 
    myTextblock.Text = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds"; 
    return; 
    } 
    else 
    { 
    myTextblock.Text = "Error, integer not entered, try again." + myTextBox.Text; 
    myLabel.Content = "Error, integer not entered, try again."; 
    return; 
    } 
} 
+0

답변에 감사드립니다. 불행히도 나는 .NET Framework 4.0이 4.5가 아니므로 IntelliSense에 이러한 기능이 나타나지 않는다는 것을 깨달았습니다. – PaulDecember

+0

그런 경우'Microsoft.Bcl.Async'를 설치하고'Task.Run' 대신'TaskEx.Run'을 사용할 수 있습니다. –