5

Tôi đang cố gắng triển khai lớp trợ giúp/lớp tiện ích .NET 4 sẽ truy xuất nguồn trang HTML dựa trên danh sách url cho công cụ webtesting. Giải pháp phải có khả năng mở rộng và có hiệu suất cao.Cách thực hiện đa luồng với yêu cầu web không đồng bộ

Tôi đã nghiên cứu và thử các giải pháp khác nhau đã có nhiều ngày, nhưng không thể tìm ra giải pháp thích hợp.

Dựa trên cách hiểu tốt nhất của tôi để đạt được mục tiêu của mình là sử dụng các truy vấn web không đồng bộ chạy song song bằng TPL.

Để có toàn quyền kiểm soát các tiêu đề, v.v ... Tôi đang sử dụng HttpWebResponse thay vì WebClient đang gói HttpWebResponse. Trong một số trường hợp, đầu ra phải được kết nối với các tác vụ khác, do đó việc sử dụng các nhiệm vụ TPL có thể có ý nghĩa.

Những gì tôi đã đạt được cho đến nay sau nhiều thử nghiệm/các cách tiếp cận khác nhau,

  1. thực hiện đồng bộ cơ bản, không đồng bộ (APM) và song song (sử dụng nhiệm vụ TPL) giải pháp để xem mức độ thực hiện các giải pháp khác nhau.

  2. Để xem hiệu suất của giải pháp song song asynchrounous, tôi đã sử dụng phương pháp APM, BeginGetResponse và BeginRead và chạy nó trong Parallel.ForEach. Tất cả mọi thứ hoạt động tốt và tôi hài lòng với hiệu suất. Bằng cách nào đó tôi cảm thấy rằng bằng cách sử dụng Parallel.ForEach đơn giản không phải là con đường để đi và ví dụ tôi không biết làm thế nào tôi sẽ sử dụng chuỗi nhiệm vụ.

  3. Sau đó, tôi đã thử hệ thống phức tạp hơn bằng cách sử dụng các nhiệm vụ để gói giải pháp APM bằng cách sử dụng TaskCompletionSource và trình lặp để lặp qua luồng APM. Tôi tin rằng giải pháp này có thể là những gì tôi đang tìm kiếm, nhưng có một sự chậm trễ kỳ lạ, một cái gì đó giữa 6-10s, xảy ra 2-3 lần khi chạy 500 url danh sách.

    Dựa trên nhật ký, quá trình thực hiện đã quay lại chuỗi đang gọi tìm nạp không đồng bộ trong vòng lặp khi xảy ra sự cố. Sự chậm trễ không xảy ra luôn khi thực hiện di chuyển trở lại vòng lặp, chỉ 2-3 lần, thời gian khác nó hoạt động tốt. Dường như chuỗi lặp sẽ tạo ra một tập hợp các tác vụ sẽ được xử lý bởi các luồng khác và trong khi hầu hết/tất cả các nhiệm vụ được hoàn thành sẽ có độ trễ (6-8s) trước khi vòng lặp tiếp tục tạo các tác vụ còn lại và các luồng khác đang hoạt động trở lại .

Nguyên tắc lặp bên trong vòng lặp là:

IEnumerable<Task> DoExample(string input) 
    { 
    var aResult = DoAAsync(input); 
    yield return aResult; 
    var bResult = DoBAsync(aResult.Result); 
    yield return bResult; 
    var cResult = DoCAsync(bResult.Result); 
    yield return cResult; 
    … 
    } 

Task t = Iterate(DoExample(“42”)); 

Tôi đang giải quyết giới hạn kết nối bằng cách sử dụng System.Net.ServicePointManager.DefaultConnectionLimit và thời gian chờ sử dụng ThreadPool.RegisterWaitForSingleObject

Câu hỏi của tôi đơn giản, cách tiếp cận tốt nhất để triển khai lớp trợ giúp/tiện ích để truy xuất các trang html là:

  • được mở rộng và có hiệu suất cao
  • webrequests sử dụng
  • thể dễ dàng bị xích vào các nhiệm vụ khác
  • có thể sử dụng thời gian chờ
  • sử dụng.NET 4 framework

Nếu bạn nghĩ rằng giải pháp sử dụng APM, TaskCompletionSource và iterator, mà tôi đã trình bày ở trên, là tốt, tôi sẽ đánh giá cao sự giúp đỡ để giải quyết vấn đề trì hoãn.

Tôi hoàn toàn mới đối với C# và phát triển Windows, vì vậy, xin đừng bận tâm nếu có điều gì đó tôi đang cố gắng không có ý nghĩa quá nhiều.

Bất kỳ trợ giúp nào sẽ được đánh giá cao vì không giải quyết được vấn đề này, tôi phải thả phát triển công cụ thử nghiệm của mình.

Cảm ơn

+0

Bạn có thể giải thích chi tiết hơn về cách bạn sử dụng trình lặp và tại sao bạn cho rằng hữu ích khi thực sự có nó như một trình lặp? – svick

+0

Sau khi thử các giải pháp khác nhau, tôi đã sử dụng các trình vòng lặp dựa trên lời khuyên của chuyên gia MS trên blog msdn. Giải pháp của tôi ít nhiều giống như trong blog, chỉ cần thêm thời gian chờ và ghi nhật ký. Tôi không có bất kỳ lý do cụ thể để sử dụng iterators và tôi mở cửa cho bất kỳ giải pháp mà các công trình. Liên kết đến đoạn mã: http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/95355648-1fa6-4b2d-a260-954c3421c453/ – Laowai

Trả lời

0

Sử dụng vòng lặp là một giải pháp tuyệt vời trong pre-TPL NET (ví dụ, điều phối và Concurrency Runtime (CCR) trong MS Robotics đã sử dụng nặng nề của họ và giúp truyền cảm hứng cho TPL). Một vấn đề là các trình vòng lặp một mình sẽ không cung cấp cho bạn những gì bạn cần - bạn cũng cần một bộ lập lịch để phân phối hiệu quả khối lượng công việc. Đó là gần thực hiện bằng đoạn Stephen Toub của bạn liên quan đến - nhưng lưu ý rằng một dòng:

enumerator.Current.ContinueWith(recursiveBody, TaskContinuationOptions.ExecuteSynchronously); 

Tôi nghĩ rằng vấn đề không liên tục bạn nhìn thấy có thể được liên kết với buộc "ExecuteSynchronously" - nó có thể gây ra một phân phối công việc không đồng đều trên các lõi/luồng có sẵn.

Hãy xem một số lựa chọn thay thế khác mà Stephen đề xuất in his blog article. Đặc biệt, hãy xem những gì chỉ cần thực hiện một chuỗi các cuộc gọi ContinueWith() đơn giản sẽ thực hiện (nếu cần, tiếp theo là kết hợp các cuộc gọi Unwrap()). Cú pháp sẽ không đẹp nhất, nhưng nó đơn giản nhất và can thiệp càng ít càng tốt với thời gian chạy trộm cắp cơ bản, vì vậy bạn hy vọng sẽ có được kết quả tốt hơn.

+0

Cảm ơn các đề xuất và nhận xét của bạn. Tôi sẽ xem xét kỹ hơn blog của Stephen. – Laowai

+0

Chắc chắn! Hãy cho chúng tôi biết bạn tìm thấy gì... –

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