2012-05-24 29 views
10

Sau khi ứng dụng của tôi bị đóng băng, tôi đã theo dõi nguyên nhân của một chuỗi đang chờ trên một tác vụ được tạo bởi Task.Delay() (hoặc TaskEx.Delay() trong .NET 4.0) mà nó đã cung cấp tính toán TimeSpan, do lỗi, được tính vào số TimeSpan với số TotalMilliseconds nhỏ hơn hoặc bằng -1 và lớn hơn -2 (ví dụ: bất kỳ vị trí nào trong khoảng từ -10000 đến -19999 bọ ve).Tại sao Task.Delay() cho phép trì hoãn vô hạn?

Dường như khi bạn vượt qua một tiêu cực TimeSpan đó là -2 mili giây hoặc thấp hơn, phương pháp này một cách chính xác ném một ArgumentOutOfRangeException, nhưng khi bạn cung cấp một TimeSpan tiêu cực từ dòng sản phẩm được mô tả ở trên, nó sẽ trả về một Task mà không bao giờ hoàn thành (bằng cách thiết lập bên dưới System.Threading.Timer đến một số dueTime trong số -1 biểu thị vô cùng). Điều đó có nghĩa là bất kỳ sự tiếp tục nào được đặt trên tác vụ đó sẽ không bao giờ thực hiện và bất kỳ chuỗi kém nào xảy ra với .Wait() trên đó Task sẽ mãi mãi bị chặn.

Điều gì có thể sử dụng có thể là Task mà không bao giờ hoàn thành? Có ai mong đợi một giá trị trả lại như vậy không? Không nên có bất kỳ giá trị âm nào được chuyển đến .Delay(), bao gồm các giá trị trong phạm vi đặc biệt đó, hãy ném một số ArgumentOutOfRangeException?

+1

Tài liệu MSDN khá rõ ràng khi cho phép -1, do đó, có vẻ như hoạt động chính xác. Không chắc chắn về trường hợp sử dụng cho tình trạng quá tải đó, nhưng nó có thể là một cách chờ đợi 'hủy bỏ' chỉ với quá tải phải mất mã thông báo hủy. –

+0

@James: Không rõ ràng khi cho phép -1, rõ ràng là không cho phép giá trị thấp hơn -1. Nó thậm chí không nói điều gì sẽ xảy ra nếu bạn vượt qua -1, không giống như tài liệu của 'System.Threading.Timer'. Nó gần như xuất hiện như danh sách tài liệu ngoại lệ được tự động tạo ra từ mã nguồn. Và nếu bạn đang chờ đợi 'hủy bỏ' chỉ, tại sao thậm chí thực hiện một cuộc gọi đến 'Task.Delay()'? –

+0

nếu bạn nghĩ rằng nó bị hỏng, hãy gửi một lỗi khi kết nối. Một tài liệu cho biết "thấp hơn -1 là không hợp lệ" là rõ ràng (với tôi) khi nói rằng -1 là hợp lệ. Nếu mục đích là -1 là không hợp lệ "thấp hơn 0 không hợp lệ" sẽ dễ viết hơn. Vì doc và code đều cho phép -1, tôi nghĩ đây là By Design, nhưng hãy thoải mái gửi một lỗi về kết nối (nhiều khả năng được xử lý bởi nhóm BCL hơn là một chuỗi SO ngẫu nhiên, tôi sẽ nghĩ :) –

Trả lời

7

Timeout.Infinite hoặc -1 là hữu ích khi bạn muốn đợi vô thời hạn cho một tác vụ lâu dài sẽ mất một khoảng thời gian không xác định để hoàn thành, nhưng cuối cùng sẽ hoàn thành.

API Win32 cũng sử dụng INFINITE không đổi = -1 cho thời gian chờ vô hạn.

Bạn thường không muốn sử dụng nó trong chuỗi giao diện người dùng vì nó có thể đóng băng giao diện người dùng (có vẻ như vấn đề của bạn). Nhưng có trường hợp sử dụng hợp lệ trong chuỗi công nhân - ví dụ: máy chủ chặn đang chờ kết nối từ máy khách.

+0

Thời gian chờ vô hạn hữu ích. Một sự chậm trễ vô hạn không phải là (và do đó bạn đoạn đầu tiên không áp dụng). Bạn muốn trì hoãn mãi mãi điều gì trên thế giới? Bạn cũng có thể không thực hiện nó. Nó không có ý nghĩa gì với tôi rằng chi tiết thực hiện của '-1' sẽ được truyền từ' System.Threading.Timer' (hoặc bộ đếm thời gian Win32) lên phương thức 'Task.Delay()'.Nó trái với nguyên tắc thiết kế của Microsoft đẩy các nhà phát triển vào "hố thành công", trừ khi có một số trường hợp sử dụng mà tôi không biết. –

+0

Ngoài ra, tôi không sử dụng nó trong một chuỗi giao diện người dùng. Đó là một dịch vụ Windows mà khi được yêu cầu dừng lại, nó phải thực hiện một thói quen tắt máy bằng cách gọi phương thức dựa trên [TAP] (http://www.microsoft.com/en-us/download/details.aspx?id=19957) có thể mất quá nhiều thời gian để chạy vì vậy nó cũng tạo ra một nhiệm vụ chậm trễ sẽ thực hiện tắt máy cưỡng bức. Sau đó nó thực hiện một '.WaitAny()' trên cả hai nhiệm vụ và vì nhiệm vụ ban đầu mất một thời gian rất dài và nhiệm vụ chậm trễ sẽ không bao giờ hoàn thành (thay vì ném một ngoại lệ), dịch vụ xuất hiện treo. –

+1

Máy chủ đang chặn kết nối từ máy khách sẽ sử dụng 'Task' không bao giờ hoàn thành như thế nào? Bạn có thể cho thấy một ví dụ? –

2

Trong các tình huống nhại, nơi tôi muốn đảm bảo rằng mã của tôi trong khối Task.WhenAny() đang xử lý một trong các tác vụ được chờ đợi chính xác, tôi có thể thử các nhiệm vụ khác và sử dụng độ trễ vô hạn để đảm bảo Nhiệm vụ .WhenAny đang xử lý tác vụ mà tôi không mô phỏng như một sự chậm trễ vô hạn.

+2

Trường hợp sử dụng thú vị, mặc dù tôi nghĩ sẽ rõ ràng hơn và rõ ràng hơn khi sử dụng 'TaskCompletionSource() mới Task' để cung cấp tác vụ không bao giờ kết thúc. –

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