原来的方法调用是这样的:
public string AskAPI(string uri)
{
return api.Query(uri);
}
其中 api 只是一个导入的 dll 引用。
现在我想为 AskAPI 方法添加一个超时功能,这样如果 api.Query 花费的时间超过 30 秒,AskAPI 就会抛出异常。
看来我将无法让它工作。任何人都可以分享他们对此的想法吗?
谢谢!
原来的方法调用是这样的:
public string AskAPI(string uri)
{
return api.Query(uri);
}
其中 api 只是一个导入的 dll 引用。
现在我想为 AskAPI 方法添加一个超时功能,这样如果 api.Query 花费的时间超过 30 秒,AskAPI 就会抛出异常。
看来我将无法让它工作。任何人都可以分享他们对此的想法吗?
谢谢!
您可以使用任务来执行此操作,这是一个示例:
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);