Tại sao C # cho phép bạn thực hiện ghi đè không đồng bộ?


16

Trong C #, khi bạn ghi đè một phương thức, nó được phép thực hiện ghi đè không đồng bộ khi phương thức ban đầu không. Đây có vẻ như hình thức nghèo nàn.

Ví dụ đưa tôi đến đây là điều này - tôi đã được đưa vào để hỗ trợ cho vấn đề kiểm tra tải. Với khoảng 500 người dùng đồng thời, quá trình đăng nhập sẽ bị hỏng trong một vòng lặp chuyển hướng. IIS đã ghi nhật ký ngoại lệ với thông báo "Mô-đun hoặc trình xử lý không đồng bộ hoàn thành trong khi hoạt động không đồng bộ vẫn đang chờ xử lý". Một số tìm kiếm khiến tôi nghĩ rằng ai đó đang lạm dụng async void, nhưng các tìm kiếm nhanh của tôi thông qua nguồn không tìm thấy gì.

Đáng buồn thay, tôi đã tìm kiếm 'async \ svoid' (tìm kiếm regex) khi tôi nên tìm kiếm một cái gì đó giống như 'async \ s [^ T]' (giả sử Nhiệm vụ không đủ điều kiện mà bạn nhận được điểm).

Những gì tôi tìm thấy sau đó là async override void onActionExecuting(...trong một bộ điều khiển cơ sở. Rõ ràng đó phải là vấn đề, và nó đã được. Sửa nó lên (làm cho nó đồng bộ vào lúc này) đã giải quyết vấn đề.

Quay lại câu hỏi: Tại sao oh tại sao bạn có thể đánh dấu ghi đè là không đồng bộ khi mã cuộc gọi không bao giờ có thể chờ đợi?


3
xin vui lòng không đăng chéo : stackoverflow.com/questions/35817558/ từ
gnat

Chính xác thì điều gì ngăn cản người gọi chờ đợi phương thức ghi đè? Tôi thấy không có trở ngại.
Martin Maat

@MartinMaat Bạn chỉ có thể chờ đợi các phương thức quay trở lại Task.
Derek Elkins rời SE

Có lẽ đó là một điểm tốt tôi đã không nhận thấy. Tôi phải kiểm tra, nhưng tôi không nhớ cảnh báo của VS về việc gọi các phương thức không đồng bộ mà không chờ đợi.
Peter T. LaComb Jr.

Câu trả lời:


16

Các async từ khóa cho phép các phương pháp sử dụng các awaitcú pháp trong định nghĩa của nó. Tôi có thể awaittrên bất kỳ phương thức nào trả về một Taskloại bất kể đó là phương thức không đồng bộ.

voidlà loại trả về hợp pháp (mặc dù không được khuyến khích ) cho phương thức không đồng bộ, vậy tại sao nó không được phép? Từ bên ngoài, asynckhông cho phép bất cứ điều gì bạn không thể làm mà không có nó. Phương pháp bạn đang gặp rắc rối có thể đã được viết để hành xử giống hệt nhau mà không đồng bộ. Định nghĩa của nó sẽ có được dài dòng hơn.

Để người gọi, một async Tphương pháp là một phương pháp thông thường mà lợi nhuận T(được giới hạn void, Taskhoặc Task<A>). Đó là một phương thức không đồng bộ không phải là một phần của giao diện. Lưu ý rằng mã sau đây là bất hợp pháp:

interface IFoo {
    async void Bar();
}

Nó (hoặc mã tương tự trong một lớp trừu tượng) tạo ra thông báo lỗi sau trong VS2012:

Công cụ sửa đổi 'async' chỉ có thể được sử dụng trong các phương thức có thân câu lệnh

Nếu tôi đã có ý định một phương pháp trong một giao diện hoặc phụ huynh lớp được thường không đồng bộ, tôi không thể sử dụng asyncđể giao tiếp đó. Nếu tôi muốn thực hiện nó với awaitcú pháp, tôi sẽ cần có các phương thức ghi đè không đồng bộ (trong trường hợp lớp cha).


1
Bạn không đề cập gì overridecả, nhưng đó là những gì câu hỏi về.
Nathan Tuggy

4
@NathanTuggy Toàn bộ điểm của câu trả lời là asynckhông thay đổi giao diện của phương thức, chỉ những gì được phép về mặt cú pháp trong định nghĩa của nó, do đó, liệu đó có phải là ghi đè hay không hoàn toàn không liên quan.
Derek Elkins rời SE

1
Hãy giải thích rằng, thay vì giả sử mọi người đã biết mọi thứ liên quan.
Nathan Tuggy

2
@NathanTuggy Tôi cảm thấy tôi đã giải thích nó. Bạn có thể hỏi một câu hỏi cụ thể về điều mà bạn bối rối hoặc bạn tưởng tượng một người bối rối khác sẽ hỏi gì không? Điều duy nhất tôi có thể nghĩ để thêm là chỉ ra rằng công cụ asyncsửa đổi chỉ có thể được áp dụng cho việc triển khai. Ví dụ, bạn không thể khai báo một phương thức không đồng bộ trong một giao diện, nhấn mạnh rằng liệu một phương thức có đồng bộ hay không không phải là một phần của giao diện.
Derek Elkins rời SE

5
Đặt lời giải thích trong câu trả lời , ý tôi là. Đó không phải là những gì bình luận trong thời gian dài.
Nathan Tuggy

10

Mục đích duy nhất của từ khóa async là để chờ đợi trong cơ thể của chức năng đó một từ khóa. Điều này là cần thiết để thêm chức năng chờ đợi không phá vỡ mã hiện có. Microsoft quyết định sử dụng để chờ một tùy chọn chọn tham gia. Đối với một chức năng không được đánh dấu không đồng bộ, bạn có thể xác định một biến có tên đang chờ mà không có vấn đề gì.

Do đó async không phải là một phần của chữ ký của hàm và không có ý nghĩa ngữ nghĩa trong mã IL được tạo. Nó là hoàn toàn có cho trình biên dịch để biết làm thế nào để biên dịch chính xác chức năng. Nó cũng hướng dẫn trình biên dịch để đảm bảo rằng chỉ có tác vụ, tác vụ <T> hoặc void được trả về.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.