You could use Tasks to do this, here's an example:
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;
}
}
Thanks to Guillaume for suggesting to use a TimeoutException.
But as Jim Mischel points out, this won't stop the task from completing, in which case it'd be best if you could modify the API you're calling because then you could make full use of the CancellationToken class which was made for this kind of thing.
Other than that, the only other quick solution I can think of (which may be inadvisable) would be to wrap the method (or combine it) with something like this:
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;
}
}
And then call it using:
Await(() => AskAPI("http://some.uri"), 30000);