2008-08-28 37 views
26

Tôi đang viết một ứng dụng cần sử dụng Timer, nhưng có khả năng rất nhiều trong số đó. Mức độ có thể mở rộng là lớp học System.Threading.Timer như thế nào? Tài liệu chỉ đơn thuần nói là "nhẹ", nhưng không giải thích thêm. Những bộ hẹn giờ này có được hút vào một sợi đơn (hoặc threadpool rất nhỏ) xử lý tất cả các cuộc gọi lại thay mặt cho một số Timer, hay không mỗi Timer có chủ đề riêng của nó?Khả năng mở rộng là System.Threading.Timer như thế nào?

Tôi đoán một cách khác để diễn đạt lại câu hỏi là: System.Threading.Timer được triển khai như thế nào?

Trả lời

29

Tôi nói điều này để đáp ứng với rất nhiều câu hỏi: Đừng quên rằng mã nguồn (được quản lý) trong khung công tác có sẵn. Bạn có thể sử dụng công cụ này để làm cho nó tất cả: http://www.codeplex.com/NetMassDownloader

Thật không may, trong trường hợp cụ thể này, rất nhiều việc thực hiện là trong mã nguồn gốc, vì vậy bạn không nhận được để nhìn vào nó ...

Họ chắc chắn sử dụng chủ đề hồ bơi chứ không phải là một thread-per-timer, mặc dù.

Cách tiêu chuẩn để thực hiện bộ sưu tập bộ đếm thời gian lớn (đó là cách hạt nhân thực hiện nội bộ và tôi nghi ngờ gián tiếp cách bộ sưu tập Timers lớn của bạn kết thúc) là duy trì danh sách được sắp xếp theo thời gian cho đến khi hết hạn - vì vậy hệ thống chỉ bao giờ phải lo lắng về việc kiểm tra bộ hẹn giờ tiếp theo sắp hết hạn, không phải toàn bộ danh sách.

Nói chung, điều này cho O (log n) để bắt đầu hẹn giờ và O (1) để xử lý bộ hẹn giờ chạy.

Chỉnh sửa: Chỉ cần tìm trong cuốn sách của Jeff Richter. Ông nói (của Threading.Timer) rằng nó sử dụng một chủ đề duy nhất cho tất cả các đối tượng Timer, thread này biết khi bộ đếm thời gian tiếp theo (tức là như trên) là do và gọi ThreadPool.QueueUserWorkItem cho callbacks khi thích hợp. Điều này có hiệu lực là nếu bạn không hoàn thành việc phục vụ một cuộc gọi lại trên một bộ đếm thời gian trước khi đến hạn tiếp theo, rằng cuộc gọi lại của bạn sẽ nhập lại trên một chủ đề nhóm khác. Vì vậy, trong tóm tắt, tôi nghi ngờ bạn sẽ thấy một vấn đề lớn với có rất nhiều giờ, nhưng bạn có thể bị cạn kiệt hồ bơi thread nếu số lượng lớn trong số họ đang bắn vào cùng một bộ đếm thời gian và/hoặc callbacks của họ đang chạy chậm.

+0

Hàng đợi ưu tiên có thể hiệu quả hơn danh sách được sắp xếp trừ khi tất cả các bộ tính giờ được thêm hàng loạt ở đầu, sau đó được sắp xếp và không được thêm vào sau. – RAL

+0

Chắc chắn - 'danh sách được sắp xếp theo thời gian cho đến khi hết hạn' có thể là một loại hàng đợi ưu tiên - tôi không ngụ ý 'danh sách có hoạt động Sắp xếp chạy qua nó' –

+1

Tôi đã dành một chút thời gian qua mã trong sscli. Lưu ý rằng các NET ThreadPool đã thay đổi vô cùng kể từ khi Rotor được phát hành, vì vậy nó hoàn toàn có thể là System.Threading.Timer cũng đã thay đổi vô cùng. Trong thời gian thực tế đã bị hỏng trong .NET 1.1 và chỉ cố định để bảo mật an toàn và ngoại lệ an toàn trong .NET 2.0 Dù sao, trong Rotor, bộ hẹn giờ được giữ trong danh sách liên kết và được kích hoạt bởi một chuỗi hẹn giờ chuyên dụng. Có một bộ đếm thời gian kích hoạt cho toàn bộ thời gian chạy (thậm chí trên nhiều miền ứng dụng). –

7

Tôi nghĩ bạn có thể muốn suy nghĩ lại về thiết kế của mình (nghĩa là, nếu bạn tự kiểm soát thiết kế). Nếu bạn đang sử dụng rất nhiều bộ đếm thời gian mà đây thực sự là một mối quan tâm cho bạn, rõ ràng có một số tiềm năng để củng cố ở đó.

Dưới đây là một bài viết tốt từ MSDN Magazine từ một vài năm trước đây mà so sánh ba lớp hẹn giờ sẵn có, và đưa ra một số cái nhìn sâu sắc vào việc triển khai của họ:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

0

^^ như DannySmurf nói: Hợp nhất chúng. Tạo một dịch vụ hẹn giờ và yêu cầu cho bộ hẹn giờ. Nó sẽ chỉ cần giữ 1 bộ đếm thời gian hoạt động (cho cuộc gọi đến tiếp theo) và lịch sử của tất cả các yêu cầu hẹn giờ và tính toán lại nó trên AddTimer()/RemoveTimer().

5

Củng cố chúng. Tạo bộ hẹn giờ dịch vụ và yêu cầu bộ hẹn giờ. Nó sẽ chỉ cần giữ 1 hoạt động timer (cho cuộc gọi do tiếp theo) ...

Đối với điều này là một sự cải tiến so với chỉ tạo ra rất nhiều đối tượng Threading.Timer, bạn phải thừa nhận rằng nó isn 't chính xác những gì Threading.Timer đã làm trong nội bộ.Tôi muốn được quan tâm để biết làm thế nào bạn đến kết luận đó (tôi đã không tháo rời các bit gốc của khuôn khổ, vì vậy bạn cũng có thể đúng).

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