原始方法调用如下:
public string AskAPI(string uri)
{
return api.Query(uri);
}
其中api只是一个导入的dll引用。
现在我想在AskAPI方法中添加一个超时功能,这样如果api.Query需要的时间比30秒长,AskAPI会抛出异常。
似乎我无法让它运转起来。任何人都可以分享他们对此的想法吗?
谢谢!
答案 0 :(得分:8)
您可以使用Tasks执行此操作,这是一个示例:
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;
}
}
感谢Guillaume建议使用TimeoutException。
但正如Jim Mischel指出的那样,这不会阻止任务完成,在这种情况下,最好是你可以修改你正在调用的API,因为那样你就可以充分利用CancellationToken类了。是为了这种事情。
除此之外,我能想到的唯一另一个快速解决方案(可能是不可取的)就是用这样的方法包装方法(或组合它):
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;
}
}
然后使用:
调用它Await(() => AskAPI("http://some.uri"), 30000);