Câu trả lời của i3arnon với TPL Dataflow là tốt; Dataflow rất hữu ích đặc biệt nếu bạn có sự kết hợp giữa mã CPU và I/O. Tôi sẽ lặp lại tình cảm của mình rằng Parallel
được thiết kế cho mã ràng buộc CPU; nó không phải là giải pháp tốt nhất cho mã dựa trên I/O và đặc biệt là không thích hợp cho mã không đồng bộ.
Nếu bạn muốn một giải pháp thay thế mà hoạt động tốt với hầu hết-I O mã/- và không cần một thư viện bên ngoài - phương pháp bạn đang tìm kiếm là Task.WhenAll
:
var tasks = uris.Select(uri => SendRequestAsync(uri)).ToArray();
await Task.WhenAll(tasks);
Đây là giải pháp dễ nhất, nhưng nó có nhược điểm bắt đầu tất cả các yêu cầu cùng một lúc. Đặc biệt nếu tất cả các yêu cầu đều đi đến cùng một dịch vụ (hoặc một tập hợp các dịch vụ nhỏ), điều này có thể gây ra thời gian chờ. Để giải quyết điều này, bạn cần phải sử dụng một số loại điều chỉnh ...
Có tính năng nào (như phân vùng TPL) kiểm soát số lượng tác vụ tối đa và tối đa HttpClient tôi có thể tạo không?
TPL Dataflow có số đẹp MaxDegreeOfParallelism
chỉ khởi động nhiều lần tại một thời điểm. Bạn cũng có thể tăng tốc mã không đồng bộ thường xuyên bằng cách sử dụng khác được xây dựng trong, SemaphoreSlim
:
private readonly SemaphoreSlim _sem = new SemaphoreSlim(50);
private async Task SendRequestAsync(Uri uri)
{
await _sem.WaitAsync();
try
{
...
}
finally
{
_sem.Release();
}
}
Trong trường hợp sử dụng Task thay vào đó, các thực hành tốt nhất cho việc tạo ra số lượng lớn trong số họ là gì? Giả sử tôi sử dụng Task.Factory.StartNew() và thêm các tác vụ đó vào danh sách và chờ tất cả chúng.
Bạn thực sự không muốn sử dụng StartNew
. Nó chỉ có một trường hợp sử dụng thích hợp (chủ nghĩa song song dựa trên nhiệm vụ động), điều cực kỳ hiếm. Mã hiện đại nên sử dụng Task.Run
nếu bạn cần đẩy công việc lên chuỗi nền. Nhưng bạn thậm chí không cần điều đó để bắt đầu, vì vậy không phải StartNew
cũng không phải Task.Run
là thích hợp ở đây.
Có một số câu hỏi tương tự về SO, nhưng không có câu hỏi nào đề cập đến mức tối đa. Yêu cầu chỉ là sử dụng các tác vụ tối đa với tối đa HttpClient.
Tối đa là nơi mã không đồng bộ thực sự trở nên phức tạp. Với mã CPU (song song), giải pháp là hiển nhiên: bạn sử dụng nhiều luồng khi bạn có lõi. (Vâng, ít nhất bạn có thể bắt đầu ở đó và điều chỉnh khi cần thiết). Với mã không đồng bộ, không rõ ràng về giải pháp. Tùy thuộc vào nhiều yếu tố - số lượng bộ nhớ bạn có, cách máy chủ từ xa phản hồi (tỷ lệ giới hạn, thời gian chờ, v.v.), v.v.
Không có giải pháp dễ dàng nào ở đây. Bạn chỉ cần kiểm tra cách ứng dụng cụ thể của bạn giao dịch với mức đồng thời cao, và sau đó tăng tốc tới một số số thấp hơn.
Tôi có một số slides for a talk mà cố gắng để giải thích khi công nghệ khác nhau phù hợp (xử lý song song, không đồng pha, TPL Dataflow, và Rx). Nếu bạn thích mô tả bằng văn bản với công thức nấu ăn, tôi nghĩ bạn có thể hưởng lợi từ số my book đối với đồng thời.
Điều gì sẽ xảy ra nếu số lượng yêu cầu đồng thời vượt quá số lượng tối đa hệ điều hành yêu cầu http có thể thực hiện? – ozgur
@ozgur Điều đó phụ thuộc vào nơi giới hạn được định cấu hình. Nhưng nếu có một thì hãy chắc chắn đặt 'MaxDegreeOfParallelism' thành cái gì đó thấp hơn thế. – i3arnon
Câu hỏi cuối cùng. Ví dụ bạn cung cấp là thích hợp cho hoạt động IO nhưng nó không đòi hỏi song song cpu? – ozgur