Tôi có một vài phương pháp máy phát vô hạn, bao gồm một số máy phát điện chạy dài và vô hạn.Những cạm bẫy cố gắng sử dụng PLINQ trên các máy phát điện chạy dài?
IEnumerable<T> ExampleOne() {
while(true) // this one blocks for a few seconds at a time
yield return LongRunningFunction();
}
IEnumerable<T> ExampleTwo() {
while(true) //this one blocks for a really long time
yield return OtherLongRunningFunction();
}
Mục tiêu của tôi là có chuỗi vô hạn kết hợp các mục từ hai ví dụ. Đây là những gì tôi đã cố gắng, sử dụng PLINQ:
IEnumerable<T> combined = new[] { ExampleOne(), ExampleTwo() }
.AsParallel()
.WithMergeOptions(ParallelMergeOptions.NotBuffered)
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.SelectMany(source => source.GetRequests());
này dường như thích hợp kết hợp hai IEnumerables thành một hình mới, với các mặt hàng từ IEnumerable
# 1 và # 2 là có sẵn bất cứ khi nào chúng xuất hiện trong một trong hai nguồn IEnumerables
:
//assuming ExampleTwo yields TWO but happens roughly 5 times
//less often then ExampleOne
Example output: one one one one one TWO one one one one one one TWO
Tuy nhiên, nó có vẻ như đôi khi (thường là sau nhiều giờ của chạy) OtherLongRunningFunction()
sẽ đi cho một thời gian dài mà không trả lại, và trong điều kiện mà khó tái sản xuất, chuỗi combined
sẽ b khóa trên nó thay vì tiếp tục trả về kết quả từ LongRunningFunction
đầu tiên. Dường như mặc dù truy vấn song song kết hợp đã bắt đầu bằng cách sử dụng hai luồng, nó đã quyết định chuyển sang một luồng sau này.
Suy nghĩ đầu tiên của tôi là "đây có thể là công việc cho RX Observable.Merge
chứ không phải cho PLINQ". Nhưng tôi đánh giá cao cả hai câu trả lời cho thấy các cách thay thế chính xác để xử lý tình huống này cũng như giải thích về cơ chế PLINQ có thể thay đổi mức độ của các giờ song song sau khi bắt đầu một truy vấn.
Tôi không thể nói rằng tôi có nhiều kinh nghiệm với PLINQ, vì vậy điều này chủ yếu sẽ không đủ tiêu chuẩn đoán: Có vẻ như bạn giả sử kết hợp 'ExampleOne()' và 'ExampleTwo()' và chạy 'AsParallel()' trên kết quả 'IEnumerable' sẽ thay thế hoàn toàn bằng cách trả lại một kết quả từ kết quả thứ nhất và một từ kết quả thứ hai. Nó có thể là giả định này là sai? Nếu vậy, bạn có thể kết thúc trong một tình huống mà chuỗi đang được xử lý trông giống như _1st 2nd 1st 2nd 1st 1st 1st 2nd 1st 2nd 1st 1st 2nd 1st 2nd 2nd 2nd ..._ Và điều đó có thể giải thích tại sao nó _appears_ như thể bạn đang bị mắc kẹt trên số hai. – Nailuj
@Nailuj Nó thực sự giống như tôi mong đợi * 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 2 * vv, 2s là khá hiếm, và có thể có thời gian dài của thời gian giữa 2s liên tiếp. Tôi hy vọng chuỗi kết hợp sẽ tiếp tục quay trở lại 1s, và thực sự, đây là những gì thực sự xảy ra đối với hầu hết các phần. Nhưng đôi khi nó cũng ngừng quay trở lại 1s. – Jimmy
Một suy nghĩ khác: có thể PLINQ bắt đầu bằng cách xử lý số lượng bằng 1 và 2 song song, nhưng vì kết thúc 1s nhanh hơn nhiều, nó sẽ xuất hiện dưới dạng chuỗi bạn mô tả. Tuy nhiên, bất cứ khi nào 1 kết thúc, "điểm" đó sẽ xen kẽ được lấp đầy bởi 1 và 2 tương ứng. Kết quả sẽ là ngay từ đầu, nó sẽ xuất hiện như thể bạn nhận được nhiều 1s và chỉ là 2 hiếm, nhưng về lâu dài "hàng đợi" các nhiệm vụ đang được xử lý sẽ được lấp đầy với 2 giây, và do đó dường như bị mắc kẹt ? Nếu không chính xác như thế này, nó có liên quan gì không? Bạn đã thực sự xác minh :-) – Nailuj