2011-08-18 33 views
11

Gần đây, tôi tình cờ gặp qua lớp AsyncEnumerator dạng Thư viện luồng điện của Jeffrey Richter, có vẻ như giải quyết được một số vấn đề mà tôi thường gặp phải khi lập trình các công cụ không đồng bộ. Ý tưởng cho lớp này đã được khoảng một thời gian bây giờ và tôi tự hỏi nếu phiên bản hiện tại của NET/C# đã tích hợp sẵn hỗ trợ cho cơ chế này ngay bây giờ hoặc nếu nó vẫn còn cần thiết để dựa vào một thư viện của bên thứ ba? Hoặc có lẽ các phiên bản .NET mới hơn có một số cách tiếp cận khác để đơn giản hóa việc lập trình không đồng bộ nhiều như AsyncEnumerator của Richter làm gì?Chúng ta vẫn cần AsyncEnumerator của Richter?

Hay nói cách khác: Có lý do nào để không bắt đầu sử dụng AsyncEnumerator của Richter ngay hôm nay không?

Edit:

Một số liên kết với thông tin về AsyncEnumerator:

Trả lời

16

Có, bạn vẫn sẽ được hưởng lợi từ AsyncEnumerator của tôi. Các công cụ luồng mới được giới thiệu trong .NET 4 (Task, Parallel, PLINQ, vv), là tất cả về đồng thời. Tức là, tất cả chúng đều lấy khối lượng công việc tính toán, chia nó ra và sinh ra nó thành nhiều luồng để khối lượng công việc có thể hoàn thành trong thời gian ngắn hơn sẽ mất 1 chuỗi để làm toàn bộ khối lượng công việc. Bạn có thể sử dụng các cấu trúc này để thực hiện đồng thời nhiều thao tác I/O đồng bộ. Tuy nhiên, các hoạt động I/O đồng bộ gây ra tất cả các luồng để chặn mà sau đó làm cho threadpool tạo ra nhiều luồng hơn. Và như vậy, nền tảng sử dụng tài nguyên của ứng dụng của bạn trong khi mức sử dụng CPU của bạn vẫn rất thấp. Điều này là rất không hiệu quả để triển khai ứng dụng của bạn và ngăn ứng dụng của bạn mở rộng quy mô.

AsyncEnumerator của tôi là tất cả về việc bắt đầu hoạt động I/O không đồng bộ mà không chặn bất kỳ chủ đề nào để sử dụng tài nguyên của ứng dụng của bạn vẫn rất thấp để ứng dụng của bạn mở rộng rất tốt. Việc sử dụng CPU vẫn thấp trong trường hợp này vì bạn đang thực hiện I/O; không phải khối lượng công việc tính toán. Trong phiên bản tiếp theo của .NET, tính năng ngôn ngữ async/await mới (mà tôi đã làm việc với Microsoft), cho phép bạn thực hiện I/O không đồng bộ và trên thực tế, các tính năng mới được mô hình hóa rất giống với AsyncEnumerator của tôi . Vì vậy, nhiều để bạn có thể mã cổng sử dụng AsyncEnumerator của tôi cho mô hình mới với rất ít thay đổi mã nguồn.

Khi người khác chỉ ra, AsyncEnumerator của tôi vẫn cung cấp các tính năng khác và hoạt động với .NET 2.0 trở lên. Vì vậy, nhiều người vẫn sẽ thấy nó khá hữu ích trong một thời gian dài.

+0

Cảm ơn bạn đã giải thích! Tôi bắt đầu sử dụng thư viện của bạn và tôi khá hài lòng với nó. Tuy nhiên tôi không chắc chắn về cách thực hiện xử lý ngoại lệ một cách chính xác. Có lẽ bạn có thể có một cái nhìn tại câu hỏi khác của tôi [ở đây] (http: // stackoverflow.com/questions/7122164/exception-handling-khi-triển khai-the-apm-pattern-với-asyncenumerator). Cảm ơn rất nhiều! –

9

Một song song rõ ràng đây là PLINQ, nhưng Richter mình dismisses this:

Jeffrey Richter ngày 4 tháng 12 năm 2008 at 2:27 PMquotereply Họ rất khác nhau. Parallel.For nói riêng là về việc thực hiện một loạt các hoạt động tính toán theo chiều ngang song song trên tất cả các CPU trong máy teh. AsyncEnumerator của tôi chủ yếu là về việc phát hành một hoặc nhiều hơn hoạt động đồng thời I/O-ràng buộc mà không có bất kỳ chủ đề nào chặn cho chúng hoàn tất.

Tuy nhiên, C# async CTP có thể hữu ích ở đây, làm cho sự tiếp tục chủ đề nhiều hơn nữa hợp lý, tức là

var bytesRead = await stream.ReadAsync(...); 
Console.WriteLine(bytesRead); // woah! we're on a different thread now! 

Ở đây, trình biên dịch C# lại viết tất cả mọi thứ xung quanh await instuctions, như vậy mà nó trở thành một gọi lại/tiếp tục đến hoạt động không đồng bộ hiện có (phải trả về giá trị "awaitable"). Một khi điều này là trong sản xuất, tôi hy vọng điều này sẽ trở thành một cách tự nhiên hơn nhiều để viết mã với sự chậm trễ nội tại do async.

+0

Từ những gì tôi đã thấy về PLINQ Tôi cũng không nghĩ rằng đó là một song song rõ ràng. Những gì tôi thích về AsyncEnumerator là bạn có thể thể hiện một chuỗi các hoạt động không đồng bộ một cách rất tự nhiên (như kết nối với máy chủ web, yêu cầu một số dữ liệu, dựa trên yêu cầu kết quả một số dữ liệu khác). Tất cả trông giống như một chương trình đồng bộ. Trên hết, bạn có hỗ trợ hủy/hết thời gian chờ và bạn không phải lo lắng về việc sắp xếp lại chuỗi giao diện người dùng. Tôi không thấy làm thế nào tôi có thể xử lý một cái gì đó như thế này với PLINQ. –

+0

@Robert là *** chính xác *** những gì đang chờ đợi, quá - trong C# thường xuyên tìm kiếm. 'var response = await GetResponse();' etc –

+0

Về từ khóa chờ đợi ... Tôi muốn gắn bó với những gì hiện có sẵn (tôi đang viết mã sản xuất) –

0

Từ câu hỏi này Asynchronous iterator Task<IEnumerable<T>>:

Nghe có vẻ giống như những gì bạn thực sự có thể tìm kiếm một cái gì đó giống như IObservable<T>, đó là loại giống như một push-based không đồng bộ IEnumerable <T>. Xem Reactive Extensions, a.k.a. Rx từ Microsoft Open Technologies (mã được cấp phép theo Apache-2.0) (không có liên kết) cho một loạt các phương thức hoạt động với IObservable <T> để làm cho nó hoạt động giống như LINQ-to-Objects và hơn thế nữa.

Sự cố với IEnumerable <T> là không có gì thực sự làm cho việc liệt kê chính nó không đồng bộ. Nếu bạn không muốn thêm một sự phụ thuộc vào Rx (mà thực sự là những gì làm cho IObservable <T> tỏa sáng), thay thế này có thể làm việc cho bạn:

public async Task<IEnumerable<char>> TestAsync(string testString) 
{ 
    return GetChars(testString); 
} 

private static IEnumerable<char> GetChars(string testString) 
{ 
    foreach (char c in testString.ToCharArray()) 
    { 
     // do other work 
     yield return c; 
    } 
} 

dù tôi muốn chỉ mà không biết những gì thực sự được thực hiện không đồng bộ, có thể có một cách tốt hơn để hoàn thành mục tiêu của bạn. Không có mã nào mà bạn đăng sẽ thực sự làm bất cứ điều gì một cách không đồng bộ và tôi không thực sự biết bất cứ điều gì trong // do other work là không đồng bộ (trong trường hợp này, đây không phải là giải pháp cho vấn đề cơ bản của bạn mặc dù nó sẽ biên dịch mã của bạn).

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