Sử dụng các câu lệnh và chờ đợi các từ khóa chơi tốt trong c #


101

Tôi gặp tình huống đang thực hiện asynccuộc gọi đến một phương thức trả về và IDisposablephiên bản. Ví dụ:

HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com"));

Bây giờ trước đây asyncở hiện trường, khi làm việc với một IDisposablephiên bản, lệnh gọi và mã sử dụng biến "response" này sẽ được bao bọc trong một câu lệnh using.

Câu hỏi của tôi là liệu đó có còn là cách tiếp cận chính xác khi asynctừ khóa được đưa vào hỗn hợp không? Mặc dù mã biên dịch, câu lệnh using vẫn hoạt động như mong đợi trong cả hai ví dụ dưới đây?

ví dụ 1

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    // Do something with the response

    return true;
}

Ví dụ 2

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    await this.responseLogger.LogResponseAsync(response);

    return true;
}

Câu trả lời:


97

Vâng, điều đó sẽ ổn.

Trong trường hợp đầu tiên, bạn thực sự đang nói:

  • Không đồng bộ đợi cho đến khi chúng tôi có thể nhận được phản hồi
  • Sử dụng nó và vứt bỏ nó ngay lập tức

Trong trường hợp thứ hai, bạn đang nói:

  • Không đồng bộ đợi cho đến khi chúng tôi có thể nhận được phản hồi
  • Không đồng bộ đợi cho đến khi chúng tôi ghi lại phản hồi
  • Loại bỏ phản hồi

Một usingcâu lệnh trong phương thức không đồng bộ là "kỳ quặc" ở chỗ Disposecuộc gọi có thể thực thi trong một chuỗi khác với chuỗi đã lấy tài nguyên (tùy thuộc vào ngữ cảnh đồng bộ hóa, v.v.) nhưng nó vẫn sẽ xảy ra ... giả sử điều bạn đang chờ đợi tất nhiên là bao giờ xuất hiện hoặc thất bại. (Giống như bạn sẽ không gọi Disposebằng mã không đồng bộ nếu usingcâu lệnh của bạn chứa lệnh gọi đến một phương thức không bao giờ trả về.)


4
Cảm ơn Jon. Trong khi hầu hết các công cụ async vẫn là voodoo với tôi, nó khá yên tâm để xem mức độ thường xuyên nó tích hợp với các tính năng .net khác và chỉ hoạt động
swingdoctor

@JonSkeet Có nên chờ đợi thậm chí được sử dụng bên trong một using(){...}khối hay đó là một khối quá mức cần thiết hoặc có thể làm giảm hiệu suất trong một số trường hợp? Có using(){...}phục vụ cùng một mục đích như await?
nam

1
@nam: Không, usingawaitphục vụ các mục đích hoàn toàn khác. Lưu ý rằng C # 8 bây giờ cũng có loại bỏ không đồng bộ. Mặc dù cần biết về vấn đề phân luồng mà câu trả lời của tôi nêu bật, điều đó chắc chắn không có nghĩa là sai khi trộn usingawait.
Jon Skeet
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.