Tôi sẽ trả lời các câu hỏi cụ thể của bạn bên dưới, nhưng bạn có thể chỉ cần đọc các bài viết mở rộng của tôi về cách chúng tôi thiết kế lợi nhuận và chờ đợi.
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/
Một số bài báo này hiện đã lỗi thời; mã được tạo khác nhau theo nhiều cách. Nhưng những điều này chắc chắn sẽ cung cấp cho bạn ý tưởng về cách nó hoạt động.
Ngoài ra, nếu bạn không hiểu cách lambdas được tạo ra dưới dạng các lớp đóng, hãy hiểu điều đó trước . Bạn sẽ không tạo ra đầu hoặc đuôi của không đồng bộ nếu bạn không có lambdas xuống.
Khi đạt đến thời gian chờ, làm cách nào thời gian chạy biết đoạn mã nào sẽ thực thi tiếp theo?
await
được tạo dưới dạng:
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
Về cơ bản là vậy. Chờ đợi chỉ là một sự trở lại ưa thích.
Làm thế nào nó biết khi nào nó có thể tiếp tục lại nơi nó đã dừng lại, và làm thế nào nó nhớ được nơi nào?
Chà, làm thế nào để bạn làm điều đó mà không cần chờ đợi? Khi phương thức foo gọi thanh phương thức, bằng cách nào đó, chúng tôi nhớ cách quay lại giữa foo, với tất cả các điểm kích hoạt foo vẫn còn nguyên vẹn, bất kể thanh nào xảy ra.
Bạn biết điều đó được thực hiện như thế nào trong trình lắp ráp. Một bản ghi kích hoạt cho foo được đẩy lên ngăn xếp; nó chứa đựng những giá trị của người dân địa phương. Tại thời điểm cuộc gọi, địa chỉ trả về trong foo được đẩy vào ngăn xếp. Khi thanh được hoàn thành, con trỏ ngăn xếp và con trỏ hướng dẫn được đặt lại về vị trí cần thiết và foo tiếp tục đi từ vị trí đã dừng.
Việc tiếp tục chờ đợi hoàn toàn giống nhau, ngoại trừ việc bản ghi được đưa vào heap vì lý do rõ ràng là chuỗi kích hoạt không tạo thành một ngăn xếp .
Ủy quyền đang chờ cung cấp khi tiếp tục nhiệm vụ chứa (1) một số là đầu vào của bảng tra cứu cung cấp cho con trỏ hướng dẫn mà bạn cần thực hiện tiếp theo và (2) tất cả các giá trị của cục bộ và dấu tạm thời.
Có một số thiết bị bổ sung trong đó; ví dụ, trong .NET, việc phân nhánh vào giữa khối try là bất hợp pháp, vì vậy bạn không thể chỉ cần gắn địa chỉ mã bên trong khối try vào bảng. Nhưng đây là chi tiết sổ sách kế toán. Về mặt khái niệm, bản ghi kích hoạt chỉ đơn giản là được chuyển vào heap.
Điều gì xảy ra với ngăn xếp cuộc gọi hiện tại, nó có được lưu bằng cách nào đó không?
Thông tin liên quan trong hồ sơ kích hoạt hiện tại không bao giờ được đưa vào ngăn xếp ngay từ đầu; nó được phân bổ khỏi đống từ lúc bắt đầu. (Chà, các tham số chính thức được truyền vào ngăn xếp hoặc trong các thanh ghi một cách bình thường và sau đó được sao chép vào vị trí đống khi phương thức bắt đầu.)
Hồ sơ kích hoạt của người gọi không được lưu trữ; sự chờ đợi có thể sẽ trở lại với họ, hãy nhớ, vì vậy họ sẽ được xử lý bình thường.
Lưu ý rằng đây là một sự khác biệt hoàn toàn giữa kiểu truyền tiếp tục đơn giản của await và cấu trúc tiếp tục gọi với-hiện tại thực sự mà bạn thấy trong các ngôn ngữ như Scheme. Trong những ngôn ngữ đó, toàn bộ phần tiếp diễn bao gồm cả phần tiếp tục quay trở lại người gọi được ghi lại bởi call-cc .
Điều gì sẽ xảy ra nếu phương thức gọi thực hiện các cuộc gọi phương thức khác trước khi nó chờ - tại sao ngăn xếp không bị ghi đè?
Các cuộc gọi phương thức đó quay trở lại, và do đó, các bản ghi kích hoạt của chúng không còn nằm trên ngăn xếp tại thời điểm chờ đợi.
Và làm thế quái nào mà thời gian chạy lại hoạt động theo cách của nó thông qua tất cả những điều này trong trường hợp ngoại lệ và ngăn xếp bị rút lại?
Trong trường hợp có một ngoại lệ chưa được nhập, ngoại lệ được bắt, lưu trữ bên trong tác vụ và được ném lại khi kết quả của tác vụ được tìm nạp.
Nhớ tất cả những gì tôi đã đề cập đến sổ sách kế toán trước đây? Việc hiểu đúng ngữ nghĩa ngoại lệ là một nỗi đau lớn, hãy để tôi nói cho bạn biết.
Khi đạt được năng suất, làm thế nào để thời gian chạy theo dõi điểm mà mọi thứ nên được chọn? Trạng thái trình lặp được bảo toàn như thế nào?
Cùng một cách. Trạng thái của người dân địa phương được chuyển lên đống và một số đại diện cho hướng dẫn MoveNext
sẽ tiếp tục vào lần sau khi nó được gọi được lưu trữ cùng với người dân địa phương.
Và một lần nữa, có một loạt các thiết bị trong khối trình vòng lặp để đảm bảo rằng các ngoại lệ được xử lý chính xác.