2014-12-19 3 views
0

매우 이상한 동작이 발생했습니다. 많은 파기 후에 나는 WFP 응용 프로그램에서 직접 기다리고있는 작업을 사용하는 것이 예상대로 작동하지 않는다는 것을 보여주는 시나리오를 발견 할 수있었습니다. 그러나, 작업을 생성하고 그 안에서 기다리고있는 것은 괜찮습니다.다른 시나리오에서 작동하는 async/WPF에서 작동하지 않는 작업이 대기 중임

(VS 2013 사용) 설명하기 위해 다음 단계를 사용했습니다. 새로운 WPF 응용 프로그램에서이 main.xaml.cs을 사용

using System.Threading; 
using System.Threading.Tasks; 
using System.Windows; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     static async Task<bool> Test_int() 
     { 
      TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 

      Thread t = new Thread(() => 
      { 
       Thread.Sleep(1000); 
       tcs.SetResult(true); 
       //Console.WriteLine("TCS set"); 
      }); 
      t.Start(); 

      //int i = tcs.Task.Result; //<-- this always works, but doesn't take advantage of await semantics 
      var ret = await tcs.Task; 

      return ret; 
     } 

     static void Test() 
     { 
      var tt = Test_int(); 
      //(1) 
      tt.Wait(); 
      //Console.WriteLine("Test done"); 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      //option 1 -- works 
      Task t = new Task(Test); 
      t.Start(); 
      t.Wait(); 

      //option 2 -- hangs indefinitely 
      Test(); 
     } 
    } 
} 

내가 볼 동작은 메소드 테스트()를 실행하면 직접 ((1) 표시된 AWAIT 라인)가 중단 된 응용 프로그램을 일으키는 것입니다, 작업 내에서 실행하면 올바르게 실행되고 완료됩니다.

작업의 컨텍스트에서 실행하여 원래 문제가 해결되었지만 문제의 원인을 이해하고 싶습니다. BTW 동일한 Test() 메서드는 콘솔 응용 프로그램에서 실행할 때 직접 작동합니다.

WPF 응용 프로그램에서 직접 실행할 때 왜 작동하지 않습니다 (같은 방식으로)?

+1

WPF에서는'Task.Wait()'을 호출하지 않아야합니다. 그것은 당신이 한 것처럼 교착 상태를 도입하는 것은 매우 쉽습니다. –

+0

@ Cory Nelson 이것은 문제의 실례입니다. 기다림은 (1) 기다리는 것이 결코 돌아 오지 않는다는 것을 보여줍니다. – OSH

+0

교착 상태는 두 개 이상의 끝을 가지고 있음을 기억하십시오. 'Wait()'는 한쪽 끝이다. 다른 하나는'await'이다. –

답변

4

내 블로그에서 설명하는 classic deadlock scenario으로 실행 중입니다. 요약하면 await은 기본적으로 "컨텍스트"를 캡처하여이를 사용하여 async 메서드를 다시 시작합니다. 이 경우 UI 컨텍스트이므로 Wait을 호출하여 UI 스레드를 차단하면 async 메서드를 다시 시작할 수없고 완료 할 수 없습니다.

적절한 해결 방법은 Wait 대신 await을 사용하는 것입니다.

또한, 당신은 Start, 또는 ThreadTask 생성자를 사용하지 말아야합니다 (대신 Task.Run를 사용하지만, 경우에만 당신 백그라운드 스레드에서 코드를 실행할 필요).

async intro blog post을 읽고 내 async best practices MSDN article을 읽는 것이 좋습니다. 그들은 당신을 도와야합니다.

+0

좋은 답변에는 유용한 링크 또는 downvote가 있기 때문에 upvote인지 확실하지 않습니다. 좋은 답변에는 정보가 포함되어 있고 링크는 포함되어 있지 않기 때문입니다. –

+1

@CoryNelson : 답변에는 필요한 모든 정보가 포함되어 있습니다. 링크에 자세한 내용이 포함되어 있습니다. –

+0

블로그 게시물은 내가 누락 된 내용이었습니다. 우수한 독서. – OSH

관련 문제