11

Tôi có một phương pháp với kiểu trả về này:Làm thế nào để concat async enumerables?

public async Task<IEnumerable<T>> GetAll() 

Nó làm cho một số cuộc gọi async thêm (số lượng không rõ) mỗi trong số đó trả về một nhiệm vụ T đếm được, và sau đó muốn concat các kết quả cho sự trở lại.

var data1 = src1.GetAll(); 
var data2 = src2.GetAll(); 
var data3 = src3.GetAll(); //and so on 

Bây giờ là đủ dễ dàng để chờ tất cả và concat kết quả để tạo ra đếm được duy nhất, nhưng tôi muốn các đếm được có sẵn ngay khi trở về cuộc gọi đầu tiên, với chờ đợi tiềm năng cho người gọi/Enumerator nếu bất kỳ cuộc gọi nào vẫn đang chờ xử lý khi kết quả có sẵn hết.

Tôi có phải cuộn tay một bản concat cho điều này, làm việc xung quanh việc thiếu sự hỗ trợ của điều tra viên khi nó được bao bọc trong một nhiệm vụ <>? Hoặc đã có một cuộc gọi thư viện trong TPL hoặc ở nơi khác có thể giúp tôi. Tôi đã nhìn vào IX, nhưng nó vẫn còn trên bản phát hành thử nghiệm và không muốn gấp nó lại.

Một lưu ý phụ, là những gì tôi đang cố gắng chống mẫu? Tôi có thể nghĩ về một biến chứng, xử lý ngoại lệ - từ phía người gọi, cuộc gọi có thể hoàn thành thành công và anh ta bắt đầu sử dụng số đếm nhưng nó có thể nổ tung vào giữa ...

+0

(Ghi chú bên cạnh) Mẫu của bạn có vẻ không đối xứng: mã _waits for_ chuỗi đầu tiên sẵn sàng, nhưng không đợi phần còn lại. – Vlad

+5

Có lẽ bạn thực sự cần 'IObservable '? Trong trường hợp đó, bạn chỉ có thể sử dụng ['Observable.Concat'] (https://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.concat%28v=vs.103%29.aspx). – Vlad

+0

@Vlad: Điểm tốt. Tôi đã nghĩ về nó khi tôi nhìn vào Ix/Rx và tôi đồng ý, phản ứng có xu hướng phù hợp với loại trường hợp sử dụng tốt hơn. Nhưng kịch bản tổng thể và ứng dụng là một kéo dựa trên một và tôi không muốn thả trong búa Rx chỉ để quay trở lại enumerables từ kết quả quan sát được. – Vivek

Trả lời

6

Có một dự án hiện có tên là Async Enumerable vấn đề này chính xác.

Bạn có thể đặt nó để sử dụng khá dễ dàng.

Ví dụ:

IAsyncEnumerable<string> GetAsyncAnswers() 
{ 
    return AsyncEnum.Enumerate<string>(async consumer => 
    { 
     foreach (var question in GetQuestions()) 
     { 
      string theAnswer = await answeringService.GetAnswer(question); 
      await consumer.YieldAsync(theAnswer); 
     } 
    }); 
} 

này cho thấy một IAsyncEnumerable<string> trong đó sản lượng một lần GetAnswer lợi nhuận. Bạn có thể để lộ một số IAsyncEnumerable<T> trong trường hợp của bạn và thực hiện cuộc gọi trong nội bộ GetAll.

tôi đang cố gắng chống mẫu? Tôi có thể nghĩ đến một biến chứng, xử lý ngoại lệ - từ phía của người gọi, cuộc gọi có thể hoàn thành thành công và ông bắt đầu sử dụng đếm được nhưng nó có thể thổi lên giữa chừng qua đó ...

tôi sẽ không nói vậy. Điều này có các sự cố có khả năng xảy ra chẳng hạn như ngoại lệ xảy ra trong nội bộ trong một trong các trường hợp đang chờ xử lý, nhưng điều này cũng có thể có khả năng xảy ra bên trong bất kỳ IEnumerable<T> nào. Chuỗi không đồng bộ là thứ cần thiết trong thực tế ngày nay của API async mới nổi.

+1

Cảm ơn. Đánh dấu là câu trả lời. Tôi đã không nhập thư viện, nhưng kết thúc bằng cách cuộn anyways của riêng tôi trong một hai dòng tương tự như mẫu của bạn, thông qua một concatenator lấy một func cho việc tiếp theo enumerable. Có lẽ tôi sẽ có một cái nhìn khác tại thư viện nếu tôi nhận được một trường hợp sử dụng rộng hơn. – Vivek

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