【发布时间】:2014-07-07 12:54:18
【问题描述】:
我有一个多层 Web 应用程序,最近我决定将我的服务层(在本例中为 WebApi)转换为异步处理。
在这方面,我将所有 WebApi 方法转换为实现任务,在 MVC 部分,我实现了一个调用 WebApi 的业务层。
我的 MVC 控制器只是使用业务层类来获取视图数据。
我对 .Net 4.5 中这个基于任务的编程有点陌生,想知道我的方法是正确的还是有缺陷的。在我的简单测试中,我发现响应时间的性能有所提高,但我不确定我的所有异步调用是否安全或容易出错。
代码示例:
WebApi 操作:
[Route("category/withnews/{count:int=5}")]
public async Task<IEnumerable<NewsCategoryDto>> GetNewsCategoriesWithRecentNews(int count)
{
return await Task.Run<IEnumerable<NewsCategoryDto>>(() =>
{
using (var UoW = new UnitOfWork())
{
List<NewsCategoryDto> returnList = new List<NewsCategoryDto>();
var activeAndVisibleCategories = UoW.CategoryRepository.GetActiveCategories().Where(f => f.IsVisible == true);
foreach (var category in activeAndVisibleCategories)
{
var dto = category.MapToDto();
dto.RecentNews = (from n in UoW.NewsRepository.GetByCategoryId(dto.Id).Where(f => f.IsVisible == true).Take(count)
select n.MapToDto(true)).ToList();
returnList.Add(dto);
}
return returnList;
}
});
}
调用此api的业务类方法(MVC应用中的NewsService类。)
public async Task<IndexViewModel> GetIndexViewModel()
{
var model = new IndexViewModel();
using (var stargate = new StargateHelper())
{
string categoriesWithNews = await stargate.InvokeAsync("news/category/withnews/" + model.PreviewNewsMaxCount).ConfigureAwait(false);
var objectData = JsonConvert.DeserializeObject<List<NewsCategoryDto>>(categoriesWithNews);
model.NewsCategories = objectData;
}
return model;
}
MVC Controller Action 获取 ViewModel
public async Task<ActionResult> Index()
{
_service.ActiveMenuItem = "";
var viewModel = await _service.GetIndexViewModel();
return View(viewModel);
}
但是,某些控制器操作是 PartialViewResults 并且因为它们是 ChildActions,所以我无法将它们转换为像 Index 操作这样的异步操作。在这种情况下我要做的是:
var viewModel = _service.GetGalleryWidgetViewModel().Result;
return PartialView(viewModel);
从同步方法调用异步方法是否正确?
添加 StargateHelper.InvokeAsync 以供参考:
public async Task<string> InvokeAsync(string path)
{
var httpResponse = await _httpClient.GetAsync(_baseUrl + path).ConfigureAwait(false);
httpResponse.EnsureSuccessStatusCode();
using (var responseStream = await httpResponse.Content.ReadAsStreamAsync())
using (var decompStream = new GZipStream(responseStream, CompressionMode.Decompress))
using (var streamReader = new StreamReader(decompStream))
{
return streamReader.ReadToEnd();
}
}
【问题讨论】:
标签: c# asp.net-mvc-4 task async-await asp.net-web-api2