【发布时间】:2018-05-26 06:41:07
【问题描述】:
我已经用头撞墙两天了,坦率地说,我对自己很生气,因为我似乎无法明白。
我在webapi 上下文中。在这个请求期间,我需要向我们的其他系统之一发送一些数据,由于计算量大和多个数据库保存等原因,这个系统返回缓慢。我需要记录这个操作的结果,无论它是否成功或不。但我不想等待它完成。
我有read,我应该从上到下一直是async await。如果我决定这样做,我将不得不转换许多方法,因为我已经深入了 3 或 4 种方法,我担心会扩展更多。
我在这里有什么选择?如果我一直异步等待,我该怎么处理堆栈中更高的方法,比如我的 WebApi 控制器?
这是我的代码,我已经尽可能地精简它。现在我在方法PushResult() 中使用Task.Result()。我的理解是阻止异步?此代码在发送请求时起作用。但是 TestLog 总是最后的,而不是第一个。因此不是异步的。
//I'm in a public service and referenced twice
private void MyEndProcess()
{
// other stuff
_vendorPushService.PushResult(); // This could take a while and I have to wait for it!
_logService.PostLog(LogType.TestLog, "Test");
}
//I'm referenced above and somewhere else in the code base
public void PushResult()
{
ExternalResultModel externalResultModel = _resultService.GetExternalResultModel();
PushedResultModel pushedResult = new PushedResultModel();
try
{
pushedResult = _vendorRequestService.PushResultAsync(externalResultModel).Result;
}
catch (Exception ex)
{
pushedResult.Success = false;
}
if (pushedResult.Success)
{
_logService.PostLog(LogType.SuccessLog, pushedResult.Message);
}
else
{
_logService.PostLog(LogType.FailedLog, pushedResult.Message);
}
}
public async Task<PushedResultModel> PushResultAsync(ExternalResultModel externalResultModel)
{
// setup the requestMessage
HttpResponseMessage responseMessage = await _httpRequestService
.SendRequest(requestMessage)
.ConfigureAwait(false);
return new PushedResultModel
{
Success = responseMessage.IsSuccessStatusCode,
Message = await responseMessage.Content.ReadAsStringAsync()
};
}
public class HttpRequestService : IHttpRequestService
{
private readonly HttpClient _httpClient;
public HttpRequestService(IHttpClientAccessor httpClientAccessor)
{
_httpClient = httpClientAccessor.HttpClient;
}
public async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage)
{
HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(requestMessage).ConfigureAwait(false);
return httpResponseMessage;
}
}
【问题讨论】:
-
如果你不愿意一直异步,那么就让一切保持同步,不要在里面放任何异步代码。您只会通过添加一些异步代码而不使整个调用堆栈异步来导致问题。
-
如果您不想等待它完成,那么这本质上是一个即发即弃的场景。这在 web api 上下文中有它自己的问题。我建议您看看这里:blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html。在回答您的实际问题方面,您可能想看看
ContinueWith,但请先阅读斯蒂芬的帖子。 -
如果您需要启动后台操作,而不是等待它完成后再将响应返回给客户端 - async await 不会有太大帮助。
-
@Evk 你能扩展一下吗?无论成功/失败,我都需要记录结果。但我不希望用户必须等待它完成。
-
然后阅读上面的链接,了解asp.net中的fire and forget jobs
标签: c# asp.net-web-api async-await asp.net-4.5