2013-08-29 34 views
5

Phương pháp ban đầu gọi là như:thời gian ra một phương pháp gọi

public string AskAPI(string uri) 
{ 
    return api.Query(uri); 
} 

nơi api chỉ đơn giản là một tham chiếu dll nhập khẩu.

Ngay bây giờ tôi muốn thêm một tính năng hết thời gian vào phương pháp AskAPI, để nếu api.Query mất nhiều thời gian hơn, nói 30 giây, AskAPI sẽ ném một ngoại lệ.

Dường như tôi sẽ không thể làm cho nó hoạt động. Bất cứ ai có thể chia sẻ suy nghĩ của họ về điều này?

Cảm ơn!

+0

Bạn sẽ phải sửa đổi 'api.Query' để thêm chức năng hết thời gian chờ. Vì bạn đã cung cấp không có thông tin về nó là gì, nó không thể cho bạn biết làm thế nào để làm như vậy. (Không có cách nào để hết thời gian chờ cuộc gọi, vì bạn không có cách nào để ngắt lời nó dựa trên những gì bạn đã đăng ở đây.) –

+0

@KenWhite api.Query cũng không nằm trong tầm kiểm soát của tôi. Bạn có nghĩa là không chỉnh sửa nó, tôi không thể thời gian ra phương pháp AskAPI? – jamesdeath123

+0

Tôi không thể trả lời rằng, bởi vì bạn đã cung cấp chính xác ba dòng mã ('{}' không tính) hoàn toàn ngoài ngữ cảnh, hoàn toàn không có thông tin khác. Dựa trên chính xác những gì bạn đã đăng, câu trả lời sẽ là "Không, bạn không thể". –

Trả lời

8

Bạn có thể sử dụng Tasks để làm điều này, sau đây là một ví dụ:

public string AskAPI(string uri, int millis) 
{ 
    using (var task = new Task<string>(() => api.Query(uri))) 
    { 
     task.Start(); 
     task.Wait(millis); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

Nhờ Guillaume cho thấy sử dụng một TimeoutException. Tuy nhiên, như Jim Mischel chỉ ra, điều này sẽ không ngăn công việc hoàn thành, trong trường hợp đó sẽ là tốt nhất nếu bạn có thể sửa đổi API mà bạn đang gọi vì sau đó bạn có thể sử dụng đầy đủ lớp CancellationToken đã được thực hiện cho loại điều này.

Khác hơn thế, chỉ là giải pháp nhanh chóng khác mà tôi có thể nghĩ đến (có thể không lưu ý) sẽ được quấn phương pháp (hoặc kết hợp nó) với một cái gì đó như thế này:

public T Await<T>(Func<T> fun, int millis) 
{ 
    using (var cancel = new CancellationTokenSource(millis)) 
    using (var task = new Task<T>(() => 
    { 
     T result = default(T); 
     var thread = new Thread(() => result = fun()); 
     thread.Start(); 
     while (!cancel.Token.IsCancellationRequested && thread.IsAlive) ; // Wait for a sign from above 
     thread.Abort(); 
     cancel.Token.ThrowIfCancellationRequested(); 
     return result; 
    }, cancel.Token)) 
    { 
     task.Start(); 
     task.Wait(millis); 
     cancel.Cancel(); 
     if (!task.IsCompleted) throw new TimeoutException(); 
     return task.Result; 
    } 
} 

Và sau đó gọi nó sử dụng:

Await(() => AskAPI("http://some.uri"), 30000); 
+1

Đừng ném 'Ngoại lệ'. Ném 'TimeoutException'. – Guillaume

+1

@Guillaume Cảm ơn vì điều đó, tôi nên dành thời gian để tìm kiếm điều đó. =) – sgbj

+2

Nhưng nhiệm vụ tiếp tục thực hiện, phải không? Nghĩa là, 'api.Query' không bị hủy bỏ? –

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