2016-07-11 5 views
2

비동기 기다리는 패턴을 잡으려고합니다.async가 잘못된 실행 순서를 기다린다

private async void asynchWork() 
{ 
    // Line 1 
    Task<string> readTask = asynchAwaitWork(); 

    // Line 2 
    synchWork(); 

    // Line 3 
    string result = await readTask; 

    // Line 4 
    Debug.WriteLine(result); 
    Debug.WriteLine("The End"); 
} 
private void synchWork() 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     Debug.WriteLine("SynchWork For i : " + i); 
     Thread.Sleep(750); 
    } 
} 

private async Task<string> asynchAwaitWork() 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     Debug.WriteLine("A-SynchWork For i : " + (i+111)); 
     Thread.Sleep(750); 
    } 

    return "finished"; 
} 

내가 1 호선은 3 호선이 완료 문자열을 반환 할 때까지 기다려야 할 것이다 다음, 2 호선과 4 호선을 실행 것으로 예상 : this 예에 따라, 나는 이 작은 프로그램을 구현했습니다. 그러나 출력을 보면 synchWork 메서드는 asynchWork 메서드 다음에 실행됩니다. I 들어

A-SynchWork : I 111

A-SynchWork : 112

A-SynchWork I의 경우 : 113

A-SynchWork I의 경우 : 114

A-SynchWork i : 115

...

I 들어 91,363,210

A-SynchWork : I 125

SynchWork 않은 : 0

SynchWork : I 들어 1

SynchWork : I 2

SynchWork 3

SynchWork i의 경우 : 4

완료

414,끝이 나는 asynchWork 방법은 buisy 기다린다는 결과를 3 호선에있을 때 synchWork 방법은 시간에 실행 될 것으로 예상. 예에서 내가 잘못 이해 한 것은 무엇입니까? 또는 결과적으로 Debug.WriteLine의 출력이 순차적으로 실행되지만 작업의 실제 순서는 내 기대에 따른 것입니까?

편집 : 의견과 답변의 도움으로 내가 배운 :

  • 를 경고를 무시하고 그 의미를 연구하지 마십시오하며 await 키워드가 대기 할 수 있습니다 사용)

  • 을 메소드 내에 생성 된 Task에 의해 실행되는 조작의 결과

편집 2 :

  • 그러나 작업이 가지고이 시작된다! 그렇지 않으면 병렬 처리가 없으며 컴파일러는 주 스레드를 통해이를 추적하고 Line 3은 실제로 Line 4에 대한 차단 기능 만 있습니다.Thread.Sleep(750) 이후

은 시뮬레이션 작업을하고 난 정말이 또한 작동 Delay 필요하지 않습니다 :

private async Task<string> asynchAwaitWork() 
{ 
    await Task.Run(()=> { 
     for (int i = 0; i < 15; i++) 
      { 
       Debug.WriteLine("A-SynchWork For i : " + (i+111)); 
       Thread.Sleep(750); 
      } 
      }); 
    return "finished";    
} 

가 대단히 감사합니다. 나는 것이 asynchAwaitWork 메인 스레드에서 작업을 시작한다는 것입니다 asynchAwaitWork에서 많은 :

+3

'asynchAwaitWork'에 대한 컴파일러 경고가 있어야합니다. 작동하지 않는 이유에 대한 단서를 제공합니다. –

+0

@ScottChamberlain이 누락되었습니다. 따라서 동 기적으로 실행됩니다. 나는이 작은 정보로부터 왜 그 이유를 이해하지 못한다. –

+3

@ 몽주 그런 다음 경고에 대한 조사를하십시오. 거기에 많은 정보가 있습니다. – Servy

답변

2

만 메인 프로그램에서 상대 :

3 행이 실행되면,이 작업은 그 안에 무엇이든 실행 라인 1이 완료에있어 보장된다.

2 번 줄에서는 작업 실행이 시작되었거나 완료되었음을 보증하지 않습니다. 당신은 그것이 병렬로 운영 될지 아닌지를 알지 못합니다. 아시다시피 실행 예약을 할 수있는 작업이 있습니다.

함수 asynchAwaitWork에서 작성한 태스크의 구현은 완전히 동기식입니다. 이 구현의 세부 사항은 결국 (이 경우에는 즉각적인) 문자열을 반환 할 Task를 반환 할 때 인쇄물을 완전히 완료하게 만듭니다.

작성한 태스크가 아무 것도 인쇄하지 않는다는 점에 유의하십시오. 현재 구현에서 "A-SynchWork For i"메시지를 인쇄하면 의 부작용이 발생하여 작업을 생성합니다.

+0

위대한 설명! 'asyncAwaitWork'에서'async Task '이 태스크를 생성하게되지만'Start (...) '또는'Start (...)'라는 코드 행이 없기 때문에 결코 병렬로 실행되지 않습니다. 실행 (...)'. 그렇기 때문에 아무 것도 인쇄하지 않는 이유가 무엇입니까? =! 'asynchAwaitWork'가 return 문에 도달하면 3 행에서'result '로 전달되는 Task에 반환 값을 할당합니다. 답변의 마지막 부분은 실제로 깨달았습니다! –

+0

더 많은 논의가 채팅 형식에 도움이 될 것입니다. 그러나 당신의'asynchAwaitWork'는'console.WriteLine ("이것은 부작용입니다. Task.FromResult ("finished")를 반환합니다. 그 작업을 기다리는 것은 그것 앞에 WriteLine과 아무 관련이 없습니다. – Martijn

1

그냥 await Task.Delay(750);Thread.Sleep(750); 교체를 배웠다. 비 동시성 작업 - 이것은 계속 작업입니다. await 키워드를 사용하여 연속 작성, 즉 병렬 처리가 시작되는 이유. 현재 스레드 ID를 출력에 추가하여 어떤 일이 발생하는지 확인합니다. 예 :이 생성되면 발견되었을

private async void asynchWork() 
{ 
    // Line 1 
    Task<string> readTask = asynchAwaitWork(); 

    // Line 2 
    synchWork(); 

    // Line 3 
    string result = await readTask; 

    // Line 4 
    Debug.WriteLine(result); 
    Debug.WriteLine("The End"); 
} 
private void synchWork() 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     Debug.WriteLine("SynchWork For i : " + i + " and thareadId = " + Thread.CurrentThread.ManagedThreadId); 
     Thread.Sleep(750); 
    } 
} 

private async Task<string> asynchAwaitWork() 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     Debug.WriteLine("A-SynchWork For i : " + (i + 111) + " and thareadId = " + Thread.CurrentThread.ManagedThreadId); 
     await Task.Delay(750); 
     //Thread.Sleep(750); 
    } 

    return "finished"; 
} 

, Task.Delay (750)은 동일한 동기화 컨텍스트를 사용한다. 당신이

[STAThread] 
void Main() 
{ 
    var window = new Window(); 
    window.Loaded += (s, e) => { 
     asynchWork(); 
    }; 
    window.ShowDialog(); 
} 
WPF

에서 코드를 실행하는 경우 포어 예를 들어, 당신은 모두가 동일한 스레드에서 일어나는 것을 볼 수 있습니다. 이므로이를 염두에 두어 await Task.Delay(750).ConfigureAwait(false);을 사용하면이를 피할 수 있습니다.

+0

이것은 콘솔 앱에서 실행되면 병렬로 실행되지만 'SyncronisationContext.Current'가 설정된 상황에서이 프로그램을 실행하면 첫 번째'asynchAwaitWork'가 실행되고'synchWork'가 모두 실행 된 다음 나머지는 실행됩니다 'asynchAwaitWork' 파일의 내용입니다. 작업readTask = Task.Run (() => asynchAwaitWork()); ' –

+0

예, Task.Delay (750)가 수행 할 작업을 기다려야합니다. 현재 상황을 계속 진행하십시오. 따라서 UI 스레드에서 WPF 응용 프로그램 (예 :)에서 실행하면 UI 스레드에서 연속이 실행됩니다. 고맙습니다, @ScottChamberlain, 당신 말이 맞아요. – tym32167

+0

@ tym32167 "await 키워드를 사용하면 연속성을 만드는 이유는 무엇입니까? 당신이 정교 할 수 있니? –

관련 문제