아래에서 구체적인 질문에 답할 것이지만, 수익을 설계하고 기다리는 방법에 대한 광범위한 기사를 읽으면 좋을 것입니다.
https://blogs.msdn.microsoft.com/ericlippert/tag/continuation-passing-style/
https://blogs.msdn.microsoft.com/ericlippert/tag/iterators/
https://blogs.msdn.microsoft.com/ericlippert/tag/async/
이 기사 중 일부는 현재 구식입니다. 생성 된 코드는 여러면에서 다릅니다. 그러나 이것들은 확실히 그것이 어떻게 작동하는지에 대한 아이디어를 줄 것입니다.
또한 람다가 클로저 클래스로 생성되는 방식을 이해하지 못하는 경우 먼저 . 람다가 없으면 앞면이나 뒷면을 비동기로 만들지 않습니다.
await에 도달하면 런타임은 다음에 실행할 코드 조각을 어떻게 알 수 있습니까?
await
다음과 같이 생성됩니다.
if (the task is not completed)
assign a delegate which executes the remainder of the method as the continuation of the task
return to the caller
else
execute the remainder of the method now
그게 기본입니다. Await는 멋진 반환 일뿐입니다.
중단 된 부분에서 다시 시작할 수있는시기를 어떻게 알 수 있으며 어디에서 어떻게 기억합니까?
어떻게 기다리지 않고 어떻게하나요? 메소드 foo가 메소드 bar를 호출 할 때, 어떻게 든 우리는 bar가 무엇을하든 상관없이 foo 활성화의 모든 지역을 그대로 유지하면서 foo의 중간으로 돌아가는 방법을 기억합니다.
어셈블러에서 어떻게 수행되는지 알고 있습니다. foo에 대한 활성화 레코드가 스택으로 푸시됩니다. 그것은 지역 주민들의 가치를 포함합니다. 호출 시점에서 foo의 반환 주소가 스택으로 푸시됩니다. bar가 완료되면 스택 포인터와 명령어 포인터가 필요한 위치로 재설정되고 foo는 중단 된 위치에서 계속 이동합니다.
await 의 연속은 활성화 시퀀스가 스택을 형성하지 않는다는 명백한 이유로 레코드가 힙에 배치된다는 점을 제외하면 정확히 동일 합니다.
대기중인 델리게이트는 작업의 연속으로 제공합니다. (1) 다음에 실행해야하는 명령 포인터를 제공하는 조회 테이블에 대한 입력 인 숫자와 (2) 로컬 및 임시의 모든 값이 포함됩니다.
거기에 몇 가지 추가 장비가 있습니다. 예를 들어, .NET에서 try 블록의 중간으로 분기하는 것은 불법이므로 단순히 try 블록 내의 코드 주소를 테이블에 붙일 수 없습니다. 그러나 이것들은 부기 세부 사항입니다. 개념적으로 활성화 레코드는 단순히 힙으로 이동됩니다.
현재 호출 스택은 어떻게됩니까? 어떻게 든 저장됩니까?
현재 활성화 레코드의 관련 정보는 처음부터 스택에 저장되지 않습니다. 처음부터 힙에서 할당됩니다. (정식 매개 변수는 정상적으로 스택이나 레지스터에 전달 된 다음 메서드가 시작될 때 힙 위치에 복사됩니다.)
발신자의 활성화 기록은 저장되지 않습니다. 기다림은 아마 그들에게 돌아올 것입니다. 기억하십시오. 그래서 그들은 정상적으로 처리 될 것입니다.
이것은 await의 단순화 된 연속 전달 스타일과 Scheme과 같은 언어에서 볼 수있는 진정한 call-with-current-continuation 구조 간의 밀접한 차이입니다. 이러한 언어에서 호출자에게 다시 계속되는 것을 포함하여 전체 연속은 call-cc에 의해 캡처됩니다 .
호출하는 메서드가 대기하기 전에 다른 메서드를 호출하면 어떻게 될까요? 스택이 덮어 쓰여지지 않는 이유는 무엇입니까?
이러한 메서드 호출이 반환되므로 해당 활성화 레코드가 더 이상 대기 시점의 스택에 없습니다.
그리고 도대체 예외와 스택 해제의 경우 런타임이이 모든 과정에서 어떻게 작동할까요?
포착되지 않은 예외가 발생하는 경우 예외가 포착되어 태스크 내부에 저장되며 태스크 결과를 가져올 때 다시 발생합니다.
내가 전에 언급했던 모든 부기를 기억하십니까? 예외 의미론을 올바르게 얻는 것은 엄청난 고통이었습니다.
수율에 도달하면 런타임이 항목을 선택해야하는 지점을 어떻게 추적합니까? 반복기 상태는 어떻게 보존됩니까?
같은 길. 지역의 상태가 힙으로 이동되고 MoveNext
다음에 호출 될 때 재개되어야 하는 명령어를 나타내는 숫자 가 지역과 함께 저장됩니다.
그리고 반복자 블록에는 예외가 올바르게 처리되는지 확인하기위한 많은 장비가 있습니다.