超时方法调用

jam*_*123 5 c# multithreading

原始方法调用如下:

public string AskAPI(string uri)
{
    return api.Query(uri);
}
Run Code Online (Sandbox Code Playgroud)

其中api只是一个导入的dll引用.

现在我想在AskAPI方法中添加一个超时功能,这样如果api.Query需要的时间比30秒长,AskAPI会抛出异常.

似乎我无法让它工作.谁能分享他们对此的看法?

谢谢!

sgb*_*gbj 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;
    }   
}
Run Code Online (Sandbox Code Playgroud)

感谢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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用以下方法调用它:

Await(() => AskAPI("http://some.uri"), 30000);
Run Code Online (Sandbox Code Playgroud)

  • 但任务继续执行,对吧?也就是说,`api.Query`没有中止? (2认同)