2010-11-16 30 views
14

Hãy xem xét các đoạn mã sau:Cách tạo phương thức async trong C# 4 theo các phương pháp hay nhất?

public static Task<string> FetchAsync() 
{ 
    string url = "http://www.example.com", message = "Hello World!"; 

    var request = (HttpWebRequest)WebRequest.Create(url); 
    request.Method = WebRequestMethods.Http.Post; 

    return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null) 
     .ContinueWith(t => 
     { 
      var stream = t.Result; 
      var data = Encoding.ASCII.GetBytes(message); 
      Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length, null, TaskCreationOptions.AttachedToParent) 
       .ContinueWith(t2 => { stream.Close(); }); 
     }) 
     .ContinueWith<string>(t => 
     { 
      var t1 = 
       Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null) 
       .ContinueWith<string>(t2 => 
       { 
        var response = (HttpWebResponse)t2.Result; 
        var stream = response.GetResponseStream(); 
        var buffer = new byte[response.ContentLength > 0 ? response.ContentLength : 0x100000]; 
        var t3 = Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null, TaskCreationOptions.AttachedToParent) 
         .ContinueWith<string>(t4 => 
         { 
          stream.Close(); 
          response.Close(); 
          if (t4.Result < buffer.Length) 
          { 
           Array.Resize(ref buffer, t4.Result); 
          } 
          return Encoding.ASCII.GetString(buffer); 
         }); 
        t3.Wait(); 
        return t3.Result; 
       }); 
      t1.Wait(); 
      return t1.Result; 
     }); 
} 

Nó sẽ trả về Task<string>, gửi yêu cầu HTTP POST với một số dữ liệu, trả lại kết quả từ máy chủ web trong một hình thức của chuỗi và được càng nhiều hiệu quả càng tốt.

  • Bạn có phát hiện bất kỳ vấn đề nào liên quan đến luồng không đồng bộ trong ví dụ trên không?
  • Bạn có thể có .Wait() bên trong .ContinueWith() trong ví dụ này
  • Bạn có thấy bất kỳ vấn đề nào khác với sự an toàn của mã này không (trừ xử lý ngoại lệ sang một bên)?
+17

Bạn nên chấp nhận một số câu trả lời từ các câu hỏi khác – Jimmy

+0

Bạn có thể muốn xem xét đổi tên đối tượng Tác vụ của mình vì đã có đối tượng Tác vụ trong .NET 4. Trong khi bạn có thể làm cho chúng hoạt động cùng nhau, có thể dễ dàng thay đổi danh pháp. –

+0

Mystere Man, tôi không có bất kỳ khai báo Task tùy chỉnh nào. Loại tác vụ tôi đang sử dụng là từ .NET 4.0 BCL. –

Trả lời

3

Nếu async liên quan đến mã C# 4.0 là lớn và xấu xí - có cơ hội được triển khai đúng cách. Nếu nó đẹp và ngắn, thì rất có thể nó không phải;)

.. mặc dù, bạn có thể làm cho nó trông hấp dẫn hơn bằng cách tạo các phương thức mở rộng trên WebRequest, Lớp dòng và dọn dẹp phương thức chính.

P.S.: Tôi hy vọng C# 5.0 với từ khóa mới là asynclibrary sẽ sớm được phát hành.

Reference: http://msdn.microsoft.com/en-us/vstudio/async.aspx

+0

Các tính năng mới trong C# 5.0 tại PDC2010: http://player.microsoftpdc.com/Session/1b127a7d-300e-4385-af8e-ac747fee677a –

+0

+1 cho số lớn và xấu xí = đúng –

+5

Bạn có thể đúng về "rất lớn và xấu xí" , nhưng tôi không thấy cách này trả lời bất kỳ câu hỏi cụ thể nào của Grief. Tôi ngạc nhiên khi nó được chấp nhận. –

0

Bạn đúng trong suy nghĩ rằng Waits là không cần thiết - Kết quả sẽ chặn cho đến khi kết quả là đã sẵn sàng.


Tuy nhiên, một cách dễ dàng hơn nữa là sử dụng các ví dụ được cung cấp trong ParallelExtensionsExtras library.

Họ đã thực hiện phần mở rộng cho WebClient mà làm chính xác những gì bạn đang tìm kiếm:

static Task<string> FetchAsync() 
{ 
    string url = "http://www.example.com", message = "Hello World!"; 

    return new WebClient().UploadStringTask(url, "POST", message); 
} 

Bạn có thể đọc thêm về nó trong this post on the Parallel Programming with .NET blog.

+0

Cảm ơn bạn đã nhập. Tại sao bạn nghĩ rằng loại 'HttpWebRequest' được đánh dấu là lỗi thời? –

+2

'HttpWebRequest' không được đánh dấu là lỗi thời, và trên thực tế' WebClient' sử dụng nó. Có thể bạn đang nghĩ đến [hàm tạo] (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.httpwebrequest.aspx). Đó * là * lỗi thời, bởi vì bạn có nghĩa vụ phải sử dụng 'WebRequest.Create' thay thế. –

+0

Rất tiếc! Sẽ sửa lỗi đó. – porges

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