Tôi đang cố gắng để hiểu thêm về async/await
và đặc biệt là cách trình biên dịch biết "tạm dừng" tại phương thức async
và await
mà không sinh ra các chuỗi bổ sung.Trình biên dịch C# biết khi nào cắt một phương thức async?
Như một ví dụ, giả sử tôi có một phương pháp async
như
DoSomeStuff();
await sqlConnection.OpenAsync();
DoSomeOtherStuff();
Tôi biết rằng await sqlConnection.OpenAsync();
là nơi phương pháp của tôi bị "treo" và các chủ đề mà gọi nó trở lại hồ bơi thread và một khi Task
đó là theo dõi việc mở kết nối hoàn thành sau đó một chủ đề có sẵn được tìm thấy để chạy DoSomeOtherStuff()
.
| DoSomeStuff() | "start" opening connection | ------------------------------------ |
| ---------------------------------------------------------- | DoSomeOtherStuff() - |
Đây là nơi tôi bị lẫn lộn. Tôi nhìn vào mã nguồn của OpenAsync
(https://referencesource.microsoft.com/#System.Data/System/Data/Common/DBConnection.cs,e9166ee1c5d11996,references) và nó
public Task OpenAsync() {
return OpenAsync(CancellationToken.None);
}
public virtual Task OpenAsync(CancellationToken cancellationToken) {
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();
if (cancellationToken.IsCancellationRequested) {
taskCompletionSource.SetCanceled();
}
else {
try {
Open();
taskCompletionSource.SetResult(null);
}
catch (Exception e) {
taskCompletionSource.SetException(e);
}
}
return taskCompletionSource.Task;
}
Tôi tưởng tượng để xem một số nơi trình biên dịch sẽ biết để "cắt đứt" sợi chỉ vì nhiệm vụ đã bắt đầu giao tiếp với một nguồn lực bên ngoài, nhưng Tôi không thực sự thấy rằng, và trên thực tế, các Open();
dường như ngụ ý rằng nó là đồng bộ chờ đợi. Ai đó có thể giải thích làm thế nào điều này trở thành mã "không đồng bộ đúng" không có chủ đề?
Vâng, việc triển khai OpenAsync như vậy không thực sự là mã "không đồng bộ đúng". – CodeFuller
Trình biên dịch C# viết lại mã của bạn, nó biến thành * hai * phương thức của một lớp ẩn. Cuộc gọi DoSomeOtherStuff() có trong phương thức thứ hai. Bất kỳ biến cục bộ nào bạn có thể có và được sử dụng trong cả hai phần sẽ trở thành các trường của lớp đó. Một cái gì đó bạn có thể nhìn thấy bằng cách sử dụng tiện ích ildasm.exe. –
@CodeFuller Bạn có thể chỉ cho tôi một ví dụ về việc triển khai "không đồng bộ đúng" của OpenAsync() không? Hoặc hiển thị cách 'OpenAsync()' ở trên có thể được viết là đúng async? – Questionaire