我们有如下所示的 Web API Controller :
public class HomeController : ApiController
{
Logger logger = new Logger();
[HttpGet, Route("")]
public IHttpActionResult Index()
{
logger.Info("Some info logging");
return Ok();
}
}
在内部,我们的记录器使用 HttpClient
将数据POST
到 Azure 事件中心。这意味着记录器有一个内部调用异步方法的同步方法。
失败的实现
当我们的记录器有一个带有 async void
签名的私有(private)方法时:
public class Logger
{
public void Info(string message)
{
LogAsync(message);
}
private async void LogAsync(string message)
{
await PostAsync(message);
}
}
我们看到以下错误:
工作实现
如果我们更改记录器以使用像这样的 async Task
签名,它会起作用:
public class Logger
{
public void Info(string message)
{
LogAsync(message);
}
private async Task LogAsync(string message)
{
await PostAsync(message);
}
}
问题
在这两种情况下,我们的日志消息都会发送到事件中心。我想知道为什么 async Task
允许 Controller 返回预期结果,而 async void
导致 InvalidOperationException
?
此外,是否有关于从同步方法调用异步代码的最佳实践?
我在这里发布了一个示例解决方案: https://github.com/kevinkuszyk/async-task-vs-async-void-sample
最佳答案
避免判断这种方法的优点,您实际问题的答案在 this question 的答案中。 .
有多种方法可以在保持该使用模式的同时修复它:
- 不要在
LogAsync()
中await
- 使用
Task.Run(() => LogAsync());
关于c# - Web API : an asynchronous operation was still pending 中的异步无效与异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41000686/