2012-02-24 33 views
25

Có một số bài viết chỉ ra rằng các cuộc gọi cơ sở dữ liệu không đồng bộ là ý tưởng tồi trong .NET.Bất kỳ bất lợi nào khi sử dụng ExecuteReaderAsync từ C# AsyncCTP

On C# Async CTP, có một phần mở rộng System.Data.SqlClient.SqlCommand gọi ExecuteReaderAsync. Tôi có một số hoạt động như bên dưới trên mã hiện tại của mình:

var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString; 

using (var conn = new SqlConnection(connectionString)) { 
    using (var cmd = new SqlCommand()) { 

     cmd.Connection = conn; 
     cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount"; 
     cmd.CommandType = System.Data.CommandType.StoredProcedure; 

     conn.Open(); 

     var reader = cmd.ExecuteReader(); 
     while (reader.Read()) { 

      //do the reading 

     } 

     conn.Close(); 
    } 
} 

Có một số hoạt động như thế này trên mã của tôi. Vì vậy, tôi đang có suy nghĩ về việc chuyển đổi chúng thành không đồng bộ.

Nhưng mặt khác, tôi không thấy nhiều thu hút về phương pháp tiếp cận này (có thể tôi không nhìn đúng hướng, ai biết!).

Vì vậy, có bất kỳ nhược điểm nào khi sử dụng mô hình lập trình không đồng bộ mới này không?

Edit:

Giả sử tôi Refactor mã như sau:

public async Task<IEnumerable<Foo>> GetDataAsync() { 

    List<Foo> foos = new List<Foo>(); 

    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString; 

    using (var conn = new SqlConnection(connectionString)) { 
     using (var cmd = new SqlCommand()) { 

      cmd.Connection = conn; 
      cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount"; 
      cmd.CommandType = System.Data.CommandType.StoredProcedure; 

      conn.Open(); 

      var reader = await cmd.ExecuteReaderAsync(); 
      while (reader.Read()) { 

       //do the reading 
       //create foos 

      } 

      conn.Close(); 
     } 
    } 

    return foos; 

} 

Theo như tôi hiểu từ các từ khóa đang chờ đợi, nó chuyển đổi mã, đó là sau khi nó, làm phần mở rộng. Ngoài ra, khi nó chạm vào từ khóa chờ đợi, nó ngay lập tức trở lại người gọi của nó bất kể trạng thái hoạt động. Khi nó kết thúc, nó quay lại và kích hoạt mã tiếp tục.

Đây là những gì tôi có trong tâm trí.

+0

Mặc dù câu trả lời được chấp nhận là hoàn hảo, tôi muốn thêm ví dụ của mình. Trong trang web của tôi, tôi đã thực hiện tất cả các phương thức hành động như Task và thực hiện tất cả các cuộc gọi db không đồng bộ. Trang web thực sự bắt đầu tải nhanh hơn –

Trả lời

50

Tôi không đồng ý với Ricka về việc này. Các lệnh DB không đồng bộ không chỉ tốt, chúng còn quan trọng trong việc đạt được quy mô, thông lượng là độ trễ. Phản đối của anh về thời gian tăng thời gian của nhóm chủ đề chỉ áp dụng cho một máy chủ web có lưu lượng giao thông thấp.

Trong trường hợp lưu lượng truy cập cao (đây là vấn đề duy nhất quan trọng), nhóm chủ đề sẽ không phải chờ các luồng mới 'tiêm'. Làm các lệnh SQL không đồng bộ là quan trọng không chỉ từ quan điểm của yêu cầu/chủ đề máy chủ web, mà còn từ quan điểm của tổng thời gian yêu cầu/độ trễ: các cuộc gọi DB không tương quan có thể được thực hiện song song, ngược lại với tuần tự. Điều này một mình kết quả thường trong những cải tiến đáng kể trong độ trễ của yêu cầu HTTP như kinh nghiệm của người sử dụng. Nói cách khác, các trang của bạn tải nhanh hơn.

Một lời khuyên mặc dù: Lệnh SQL không thực sự không đồng bộ cho đến khi bạn bật Asynchronous Processing=true trên chuỗi kết nối. Trong khi điều này không được thiết lập (và theo mặc định không phải là, Edit:. Bắt đầu với .NET Framework 4.5 < Asynchronous Processing is no longer required) của bạn 'asyncronous' các cuộc gọi đến BeginExecuteReader là gì, nhưng một giả, cuộc gọi sẽ khởi động một thread và chặn rằng chủ đề. Khi xử lý đúng không đồng bộ được bật trong chuỗi kết nối thì cuộc gọi thực sự không đồng bộ và cuộc gọi lại được dựa trên hoàn thành IO.

Một lời cảnh báo: lệnh SQL không đồng bộ sẽ hoàn thành ngay sau khi kết quả đầu tiên trả lại cho khách hàng và thông báo thông tin được tính là kết quả.

create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount 
as 
begin 
print 'Hello'; 
select complex query; 
end 

Bạn đã mất tất cả lợi ích của việc không đồng bộ. Các print tạo ra một kết quả được gửi lại cho khách hàng, mà hoàn thành lệnh async và thực hiện trên hồ sơ khách hàng tiếp tục và tiếp tục với 'reader.Read()'. Bây giờ rằng sẽ chặn cho đến khi truy vấn phức tạp bắt đầu tạo kết quả. Bạn yêu cầu 'ai đặt print trong quy trình?' nhưng print có thể được cải trang thành một cái gì đó khác, có lẽ một cái gì đó vô tội trông như một số INSERT thực hiện mà không cần trước tiên phát hành SET NOCOUNT ON.

+0

* "Lệnh không thực sự không đồng bộ cho đến khi bạn bật Xử lý Không đồng bộ = true trên chuỗi kết nối." * Có còn được áp dụng không nếu tôi sử dụng mô hình lập trình async mới như tôi đã nêu trên câu hỏi của mình? – tugberk

+2

Chúa tể, người đưa ra các quyết định thiết kế như thế này? Những gotchas là vô lý. –

+0

@tugberk: Tôi chắc chắn 'ExecuteReaderAsync' không là gì ngoài trình bao bọc xung quanh' BeginExecuteReader'/'EndExecuteReader', do đó yêu cầu chuỗi kết nối cũng áp dụng cho nó. –

0

tôi nhận thấy rằng những câu dưới đây không được trả lời:

Vì vậy, là có bất kỳ nhược điểm của việc sử dụng mô hình lập trình async mới này ở đây?

Các bất lợi đó là rất tối thiểu (cpu nhỏ/bộ nhớ nhỏ afaik), đó là bởi vì có khả năng xảy ra bất kỳ mã chạy sau một tuyên bố chờ đợi thể chạy trên một sợi riêng biệt, một máy trạng thái tồn tại để lưu trữ trạng thái của luồng đang chạy để việc tiếp tục công việc có thể được xử lý trên một luồng khác. Bạn có thể đọc thêm về số await/async statemachine on Dixin's Blog - Understanding C# async/await (1) Compilation.

Các vấn đề liên quan