Gần đây tôi dường như không thể có đủ chức năng bất ngờ async-chờ đợi mẫu của C # 5.0. Bạn đã ở đâu trong suốt cuộc đời của tôi?
Tôi hoàn toàn hồi hộp với cú pháp đơn giản, nhưng tôi gặp một khó khăn nhỏ. Vấn đề của tôi là các hàm async có một khai báo hoàn toàn khác với các hàm thông thường. Vì chỉ các chức năng async mới có thể chờ đợi trên các chức năng không đồng bộ khác, khi tôi đang cố gắng chuyển một số mã chặn cũ sang async, tôi có hiệu ứng domino của các chức năng mà tôi phải chuyển đổi.
Mọi người đã coi đây là một sự phá hoại của zombie . Khi async bị cắn trong mã của bạn, nó sẽ ngày càng lớn hơn. Quá trình chuyển không khó, chỉ cần đưa async
vào khai báo và gói giá trị trả về Task<>
. Nhưng thật khó chịu khi phải làm đi làm lại nhiều lần khi chuyển mã đồng bộ cũ.
Đối với tôi, nó sẽ tự nhiên hơn nhiều nếu cả hai loại chức năng (không đồng bộ và đồng bộ cũ đơn giản) có cùng một cú pháp. Nếu đây là trường hợp, chuyển sẽ không mất nỗ lực và tôi có thể chuyển đổi không đau đớn giữa hai hình thức.
Tôi nghĩ rằng điều này có thể làm việc nếu chúng ta tuân theo các quy tắc sau:
Các chức năng Async sẽ không yêu cầu
async
khai báo nữa. Các loại trả lại của họ sẽ không phải được bọc trongTask<>
. Trình biên dịch sẽ tự xác định một hàm async trong quá trình biên dịch và thực hiện tác vụ <> gói tự động khi cần.Không còn các cuộc gọi quên và quên đến các chức năng không đồng bộ. Nếu bạn muốn gọi một chức năng không đồng bộ, bạn sẽ cần chờ đợi trên đó. Tôi hầu như không sử dụng lửa và quên mọi cách, và tất cả các ví dụ về tình trạng chủng tộc điên rồ hoặc bế tắc dường như luôn dựa trên chúng. Tôi nghĩ rằng họ quá khó hiểu và "mất liên lạc" với suy nghĩ đồng bộ mà chúng ta cố gắng tận dụng.
Nếu bạn thực sự không thể sống mà không có lửa và quên, sẽ có cú pháp đặc biệt cho nó. Trong mọi trường hợp, nó sẽ không phải là một phần của cú pháp hợp nhất đơn giản mà tôi đang nói đến.
Từ khóa duy nhất bạn cần để biểu thị một cuộc gọi không đồng bộ là
await
. Nếu bạn đang chờ, cuộc gọi không đồng bộ. Nếu bạn không, cuộc gọi hoàn toàn đồng bộ cũ (hãy nhớ rằng, chúng tôi không có lửa và quên nữa).Trình biên dịch sẽ tự động xác định các chức năng không đồng bộ (vì chúng không còn khai báo đặc biệt nữa). Quy tắc 4 làm cho việc này trở nên rất đơn giản - nếu một chức năng có một
await
cuộc gọi bên trong, thì đó là async.
Điều này có thể làm việc? hoặc tôi đang thiếu một cái gì đó? Cú pháp hợp nhất này trôi chảy hơn nhiều và có thể giải quyết hoàn toàn sự phá hoại của zombie.
Vài ví dụ:
// assume this is an async function (has await calls inside)
int CalcRemoteBalanceAsync() { ... }
// assume this is a regular sync function (has no await calls inside)
int CalcRemoteBalance() { ... }
// now let's try all combinations and see what they do:
// this is the common synchronous case - it will block
int b1 = CalcRemoteBalance();
// this is the common asynchronous case - it will not block
int b2 = await CalcRemoteBalanceAsync();
// choosing to call an asynchronous function in a synchronous manner - it will block
// this syntax was used previously for async fire-and-forget, but now it's just synchronous
int b3 = CalcRemoteBalanceAsync();
// strange combination - it will block since it's calling a synchronous function
// it should probably show a compilation warning though
int b4 = await CalcRemoteBalance();
Lưu ý: đây là phần tiếp theo của một cuộc thảo luận liên quan thú vị trong SO
await
ngay lập tức. Bạn có thể làm một cái gì đó như var task = FooAsync(); Bar(); await task;
. Làm thế nào tôi sẽ làm điều này trong đề xuất của bạn?
async
. Tôi nghĩ đó là một trong những lợi thế lớn của async
- await
: nó cho phép bạn dễ dàng soạn các hoạt động không đồng bộ (và không chỉ theo cách đơn giản nhất là "bắt đầu A, chờ A, bắt đầu B, chờ B"). Và đã có một cú pháp đặc biệt chính xác cho mục đích này: nó được gọi await
.