Tôi đang tìm một cách hiệu quả để ném một ngoại lệ thời gian chờ nếu một phương thức đồng bộ mất quá nhiều thời gian để thực thi. Tôi đã nhìn thấy một số mẫu nhưng không có gì mà hoàn toàn làm những gì tôi muốn.Giám sát một phương pháp đồng bộ cho thời gian chờ
gì tôi cần phải làm
- Kiểm tra rằng phương pháp đồng bộ hóa không vượt quá SLA của nó
- Nếu nó ném một ngoại lệ timeout
tôi làm không phải chấm dứt phương thức đồng bộ hóa nếu nó thực thi quá lâu. (Nhiều lần hỏng hóc sẽ làm hỏng bộ ngắt mạch và ngăn chặn lỗi tầng)
Giải pháp của tôi cho đến nay được hiển thị bên dưới. Lưu ý rằng tôi chuyển một CancellationToken sang phương thức đồng bộ với hy vọng rằng nó sẽ đáp ứng yêu cầu hủy bỏ khi hết thời gian chờ. Ngoài ra giải pháp của tôi trả về một nhiệm vụ mà sau đó có thể được chờ đợi trên vv như mong muốn bằng mã gọi của tôi.
Mối quan tâm của tôi là mã này tạo hai nhiệm vụ cho mỗi phương pháp đang được giám sát. Tôi nghĩ TPL sẽ quản lý tốt điều này, nhưng tôi muốn xác nhận.
Điều này có hợp lý không? Có cách nào tốt hơn để làm điều này?
private Task TimeoutSyncMethod(Action<CancellationToken> syncAction, TimeSpan timeout)
{
var cts = new CancellationTokenSource();
var outer = Task.Run(() =>
{
try
{
//Start the synchronous method - passing it a cancellation token
var inner = Task.Run(() => syncAction(cts.Token), cts.Token);
if(!inner.Wait(timeout))
{
//Try give the sync method a chance to abort grecefully
cts.Cancel();
//There was a timeout regardless of what the sync method does - so throw
throw new TimeoutException("Timeout waiting for method after " + timeout);
}
}
finally
{
cts.Dispose();
}
}, cts.Token);
return outer;
}
Edit:
Sử dụng @ câu trả lời Timothy của tôi hiện nay đang sử dụng này. Mặc dù không ít mã hơn nhưng nó rõ ràng hơn rất nhiều. Cảm ơn!
private Task TimeoutSyncMethod(Action<CancellationToken> syncAction, TimeSpan timeout)
{
var cts = new CancellationTokenSource();
var inner = Task.Run(() => syncAction(cts.Token), cts.Token);
var delay = Task.Delay(timeout, cts.Token);
var timeoutTask = Task.WhenAny(inner, delay).ContinueWith(t =>
{
try
{
if(!inner.IsCompleted)
{
cts.Cancel();
throw new TimeoutException("Timeout waiting for method after " + timeout);
}
}
finally
{
cts.Dispose();
}
}, cts.Token);
return timeoutTask;
}
Bạn đang sử dụng .NET 4.5 và async/chờ đợi? –
http://stackoverflow.com/questions/299198/implement-c-sharp-generic-timeout –
Robert: Cảm ơn, mối quan tâm của tôi là Thread.Abort(). Tôi không làm thế. Có vẻ quá quyết liệt. Trong trường hợp của tôi, tôi không cần phải hủy bỏ. – Andre