2014-10-30 12 views
6

Tôi không hoàn toàn 'nhận' không đồng bộ và đang chờ đợi, và tôi đang tìm một số giải thích rõ ràng về một vấn đề cụ thể mà tôi sắp giải quyết. Về cơ bản, tôi cần phải viết một số mã sẽ xử lý một kết nối TCP. Về cơ bản nó sẽ chỉ nhận dữ liệu và xử lý dữ liệu cho đến khi kết nối được đóng lại.async/await vs BeginRead, EndRead

Tôi thường viết mã này bằng cách sử dụng mẫu NetworkStream BeginRead và EndRead, nhưng vì mẫu async/await là sạch hơn nhiều, tôi bị cám dỗ sử dụng thay vào đó. Tuy nhiên, vì tôi thừa nhận không hoàn toàn hiểu chính xác những gì liên quan đến chúng, tôi hơi cảnh giác với hậu quả. Liệu người ta có sử dụng nhiều tài nguyên hơn người kia hay không; một người sẽ sử dụng một chủ đề mà người khác sẽ sử dụng IOCP, v.v.

Thời gian ví dụ phức tạp. Hai làm điều tương tự - đếm byte trong một dòng:

class StreamCount 
{ 
    private Stream str; 
    private int total = 0; 
    private byte[] buffer = new byte[1000]; 

    public Task<int> CountBytes(Stream str) 
    { 
     this.str = str; 

     var tcs = new TaskCompletionSource<int>(); 
     Action onComplete =() => tcs.SetResult(total); 
     str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete); 

     return tcs.Task; 
    } 

    private void BeginReadCallback(IAsyncResult ar) 
    { 
     var bytesRead = str.EndRead(ar); 
     if (bytesRead == 0) 
     { 
      ((Action)ar.AsyncState)(); 
     } 
     else 
     { 
      total += bytesRead; 
      str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState); 
     } 
    } 
} 

... Và ...

public static async Task<int> CountBytes(Stream str) 
    { 
     var buffer = new byte[1000]; 
     var total = 0; 
     while (true) 
     { 
      int bytesRead = await str.ReadAsync(buffer, 0, 1000); 
      if (bytesRead == 0) 
      { 
       break; 
      } 
      total += bytesRead; 
     } 
     return total; 
    } 

Để đôi mắt của tôi, cách async có vẻ sạch hơn, nhưng có mà ' trong khi (true) 'vòng lặp mà bộ não không suy giảm của tôi nói với tôi là sẽ sử dụng một chuỗi phụ, nhiều tài nguyên hơn, và do đó sẽ không mở rộng quy mô cũng như các tài nguyên khác. Nhưng tôi khá chắc chắn đó là sai. Có phải những điều này cũng giống như vậy không?

Trả lời

7

Để mắt của tôi, cách không đồng nhất trông sạch hơn, nhưng có vòng lặp 'while (true)' mà bộ não chưa được đào tạo của tôi cho biết sẽ sử dụng thêm sợi, nhiều tài nguyên hơn cũng như cái còn lại.

Không, nó sẽ không. Vòng lặp sẽ chỉ chỉ sử dụng một chuỗi khi nó thực sự đang chạy mã ... giống như trong cuộc gọi BeginRead của bạn. Biểu thức await sẽ trả về quyền kiểm soát cho bất kỳ mã gọi nào, đã đăng ký tiếp tục nhảy ngược lại đúng vị trí trong phương thức (trong một chuỗi thích hợp, dựa trên ngữ cảnh đồng bộ hóa) và sau đó tiếp tục chạy cho đến khi nó kết thúc của phương thức hoặc truy cập biểu thức await khác. Đó chính xác là những gì bạn muốn :)

Cần tìm hiểu thêm về cách hoạt động của đồng bộ/chờ đợi hoạt động sau hậu trường - bạn có thể muốn bắt đầu với the MSDN page on it, làm điểm nhảy.

+0

Điều đó rất hữu ích! Thực sự hữu ích. Tôi sẽ cung cấp cho các trang MSDN một đọc kỹ lưỡng quá. Tôi nghĩ rằng các sơ đồ dòng chảy làm tôi sợ hãi trước đây, nhưng tôi sẽ dũng cảm! :) [sẽ chấp nhận khi tôi có thể] – Barguast

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