使用VS2013,EF6.1.1,MVC5,.net 4.5。
我刚开始第一次查看async / await,我不确定这是否正确。它似乎工作,但它可以更简单吗?我似乎在很多地方坚持异步/等待一个方法调用多个层。
为简洁起见,所有代码都已简化。
在我的MVC控制器操作方法中,我有:
public async Task<ActionResult> TestAction1()
{
var testResponse = await _testService.TestMethod1(1);
if (testResponse != null)
{
_unitOfWork.CommitAsync();
return View(testResponse);
}
return RedirectToAction("TestAction2");
}
我的服务类如下:
public class TestService : ITestService
{
public async Task<TestObject> TestMethod1()
{
var testObject1 = await privateMethod1Async();
if (testObject1 != null) return testObject1;
testObject1 = await privateMethod2Async();
return testObject1;
}
private async Task<TestObject> privateMethod1Async()
{
return await _testRepository.FirstOrDefaultAsync();
}
private async Task<TestObject> privateMethod2Async()
{
return await _testRepository.FirstOrDefaultAsync();
}
}
我的存储库方法:
public async Task<TEntity> FirstOrDefaultAsync()
{
return await _entitySet.FirstOrDefaultAsync();
}
基本上,我有一个调用服务方法的控制器方法。服务方法是以异步方式调用数据库层两次。但我觉得我正在改变每一个方法和层来处理异步,我不确定我这里的内容是否正确。
其次,在控制器方法中,我不确定如何异步调用工作单元的提交方法。具有&#34; _unitOfWork.CommitAsync();&#34;的行。我不能坚持等待&#34;等待&#34;在它之前,因为它是一种无效方法。
有什么想法吗?
编辑1
以下是对EF的存储库方法调用的完整版本:
public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>>
predicate, params
Expression<Func<TEntity, object>>[]
includeProperties)
{
IQueryable<TEntity> query = EntitySet;
if (includeProperties != null && includeProperties.Any())
{
query = IncludeProperties(query, includeProperties);
}
return await query.FirstOrDefaultAsync(predicate);
}
答案 0 :(得分:8)
我在你的代码中看到了一个重复出现的模式:
private async Task<TestObject> privateMethod2Async()
{
return await _testRepository.FirstOrDefaultAsync();
}
如果你有一个只用查询数据库Task<T>
的单行程序,你可以避免await
导致的状态机分配,并简单地将热任务返回给调用者(如无论如何,他可能会在电话链的上方等待它:
private Task<TestObject> privateMethod2Async()
{
return _testRepository.FirstOrDefaultAsync();
}
请注意,async-await
会让您一直&#34; async&#34; ,这就是异步的本质。如果可能,请确保将可以使用Task.WhenAll
并发运行的任务分组(例如,不确定这可能是最好的示例):
public async Task<TestObject> TestMethod1()
{
var testObject1 = await privateMethod1Async();
if (testObject1 != null) return testObject1;
testObject1 = await privateMethod2Async();
return testObject1;
}
可能会变成:
return Task.WhenAny(privateMethod1Async(), privateMethod2Async());
鉴于其中一种方法适用于返回类型。
修改强>
添加async / await的一般规则经验法则是什么?是 它是一个进行其他处理的方法吗?哪,正如你所指出的那样 这个方法没有?
如果您希望对返回的await
进行更多处理,则需要使用Task
。如果您想要的只是返回实际的Task
,则无需等待它,您只需返回热门任务即可。这是我使用的一般规则。另请注意,使用return await
与简单return
时,异常处理会有所不同。
您可以在At the end of an async method, should I return or await?和Any difference between "await Task.Run(); return;" and "return Task.Run()"?
中详细了解相关内容答案 1 :(得分:3)
async-await
确实有在您的代码库中向上爬行的倾向,并且完全没问题。你应该尽可能地让它上升(在UI事件处理程序中,由于async-void
和UI SynchronizationContext
的组合,它可能一直上升到顶部
如果不再可能(例如控制台应用程序的根目录),您只需Wait
返回的任务:
var task = RunAsync();
task.Wait();
甚至更好,您可以使用Stephen Cleary's AsyncContext
:
AsyncContext.Run(RunAsync);