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;
}
这显然不适合计算密集型任务,如果可以使用真正的取消支持,就应该使用它。
我需要从 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;
}
这显然不适合计算密集型任务,如果可以使用真正的取消支持,就应该使用它。