C#:如何在异步方法超时的情况下从 Web 服务正确执行自动生成的方法?

C#: How to correctly execute auto-generated methods from web service with a timeout in an async method?

我需要从 WSDL 中指定的 Web 服务调用一些方法。 VisualStudio 为我创建了相应的方法,包括异步变体。该文档为这些方法指定了(不同的)超时,其中一些可能需要几分钟。那么实现这个的最佳方法是什么?

我有两种方法,但我不确定哪一种更好,或者我是否应该做一些完全不同的事情:

变体 1:使用生成的异步方法和 task.Wait 而不是 await:

public async Task<ResultType> MyMethod1Async()
{
    CancellationTokenSource cts = new CancellationTokenSource();
    cts.CancelAfter(60000);
    Task<ResultType> task = MyWebService.getSomeObjectAsync();
    task.Wait(cts.Token);
    return task.Result;
}

变体 2:在 Task.Run 中执行生成的同步方法:

public async Task<ResultType> MyMethod2Async()
{
    CancellationTokenSource cts = new CancellationTokenSource();
    cts.CancelAfter(60000);
    Task<ResultType> task = Task.Run(
        () => MyWebService.getSomeObject(),
        cts.Token);
    return await task;
}

这两个选项都不符合您的要求。

无论超时如何,变体 1 都会在 task.Result 时阻塞。一旦方法开始,变体 2 将不会被取消 运行

如果异步任务不支持取消,你能做的最好是在达到超时时return给调用者,让任务在后台继续,任何最终结果都将被忽略.例如:

    public async Task<ResultType> MyMethodAsync<T>(TimeSpan timeout)
    {

        var task = SomeAsyncMethod<ResultType>();
        var timeoutTask = Task.Delay(timeout);
        var completedTask = await Task.WhenAny(task, timeoutTask);

        if (completedTask == timeoutTask)
        {
            // Handle timeout somehow
            throw new TimeoutException("...");
        }

        return task.Result;
    }

这显然不适合计算密集型任务,如果可以使用真正的取消支持,就应该使用它。