在c#中何时需要异步和等待?
正如标题所说。我想知道我是否正在写异步,并在不需要时等待它 我见过这样的带有async标记的方法在c#中何时需要异步和等待?,c#,asp.net,.net,asynchronous,C#,Asp.net,.net,Asynchronous,正如标题所说。我想知道我是否正在写异步,并在不需要时等待它 我见过这样的带有async标记的方法 public async Task CreateAsync(User user) { if (_context.Entry<User>(user).State == EntityState.Detached) { _context.Set<User>().Add(user); } _context.Entry<User&
public async Task CreateAsync(User user)
{
if (_context.Entry<User>(user).State == EntityState.Detached)
{
_context.Set<User>().Add(user);
}
_context.Entry<User>(user).State = EntityState.Added;
await _context.SaveChangesAsync();
}
如果希望在方法返回时完成
savechangesync
操作,或者需要对异步操作的结果执行某些操作,那么只需要使用wait
。在这种情况下,您没有使用它做任何事情,因此最好不要使用异步方法,并避免生成,从而生成更高效的代码
关于你的第二次编辑,你是正确的。尽管该方法将在遇到第一个await
时立即返回,但所有其他等待的语句都将在线程池上逐个执行,然后更新任务的结果。因此,如果您等待AddPermissions
,则只有在所有内部permissionService.AddAsync
调用完成后,该语句才会完成,除非引发异常
如果需要,还可以并行执行permissionService.AddAsync
调用,方法是将返回的任务存储在列表中,然后等待Task.whalll
private async Task AddPermissions(DataContext context)
{
var permissionService = new PermissionService(context);
List<Task> permissionRequests = new List<Task>();
permissionRequests.Add(permissionService.AddAsync(new Permission("CanView", "View company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add and view company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit and view company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete and view company record")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new pages")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdite", "Edit existing pages")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete a page")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new page content")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit existing page content")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete page content")));
await Task.WhenAll(permissionRequests);
}
private async Task AddPermissions(DataContext上下文)
{
var permissionService=新permissionService(上下文);
List permissionRequests=新列表();
permissionRequests.Add(permissionService.AddAsync(新权限(“CanView”,“查看公司”)));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanAdd”,“添加并查看公司”));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanEdit”、“编辑和查看公司”));
permissionRequests.Add(permissionService.AddAsync(新权限(“candelite”,“删除并查看公司记录”));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanAdd”,“添加新页面”)));
添加(permissionService.AddAsync(新权限(“CanEdite”,“编辑现有页面”));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanDelete”,“删除页面”));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanAdd”,“添加新页面内容”));
添加(permissionService.AddAsync(新权限(“CanEdit”,“编辑现有页面内容”));
permissionRequests.Add(permissionService.AddAsync(新权限(“CanDelete”,“删除页面内容”));
等待任务。WhenAll(许可请求);
}
因此,每次调用permissionService.AddAsync
都会启动请求并将相应的任务添加到列表中。启动所有请求后,您可以使用等待任务等待所有请求的完成。当所有请求完成时,这将等待所有请求完成或返回错误。抛出的任何异常都将存储在从task.whalll
返回的任务中。等待该任务将重新显示第一个异常,但您可以使用包含
AggregatedException
,它依次包含所有抛出的异常。这个主题可能很深,但这里是一个高级概述
上面发布的两个版本的代码之间有一个关键区别。。但首先是重要的相似性
它们都告诉\u context
异步保存更改。。因为这就是savechangesync
的实现方式
现在,的区别是
在第一个版本中,当您使用async
和await
关键字时,await
调用之后的任何代码(在本例中,await
调用是函数中的最后一个调用),编译器将其转换为一个延续,并假定在await
调用完成后执行(异步)。
这包括任何可能包装异步调用的异常处理
相反,在第二个版本中,当我们将异步调用的返回值作为任务时,当异步操作已经启动,但尚未完成时,执行将继续在该方法中进行(编译器将而不是转为继续)。在异步操作完成后,没有任何代码被设置为执行(除非您在任务对象上明确使用.ContinueWith
)
为什么要用一个而不是另一个?
同样,在高级async
和await
应该适合于正常情况,在正常情况下,您希望利用编译器为您做一些魔术,以便更容易处理异步调用。。但是,对于某些场景,它也不太灵活。示例-如果要异步启动10个ping操作,然后在所有10个操作完成后编写一个延续,该怎么办。对于每个异步ping,使用async
和wait
关键字是不可能的。(对wait的第一个调用使代码的其余部分成为第一个异步调用的延续)
在internet上搜索更多有关async
wait
的详细信息。。它可能非常深入,但值得理解细节。第二个版本稍微更有效,但它不允许您在不重写代码以使用async/await的情况下返回并添加更多代码
差不多就是这样。如果我在代码库中看到任何一种模式,我都不会抱怨。更简单的方法是调用Task.Factory.StartNew
Task.Factory.StartNew(() => new Permission("CanView", "View company"));
Task.Factory.StartNew(() => new Permission("CanAdd", "Add and view company"));
...
谢谢你的回答,我添加了一个编辑,一旦用户被添加到数据库中,它就会返回一个用户。你是说这种方法应该像我写的那样使用async/await关键字吗。其他方法应该省略它们(尽管如果它们存在的话还不错)我会删除wait
,方法的客户端也可以等待结果。编辑了我的问题1
public Task<User> FindByIdAsync(long userId)
{
return _context.Users.FindAsync(userId);
}
public async Task<User> FindByIdAsync(long userId)
{
return await _context.Users.FindAsync(userId);
}
private async Task AddPermissions(DataContext context)
{
var permissionService = new PermissionService(context);
await permissionService.AddAsync(new Permission("CanView", "View company"));
await permissionService.AddAsync(new Permission("CanAdd", "Add and view company"));
await permissionService.AddAsync(new Permission("CanEdit", "Edit and view company"));
await permissionService.AddAsync(new Permission("CanDelete", "Delete and view company record"));
await permissionService.AddAsync(new Permission("CanAdd", "Add new pages"));
await permissionService.AddAsync(new Permission("CanEdite", "Edit existing pages"));
await permissionService.AddAsync(new Permission("CanDelete", "Delete a page"));
await permissionService.AddAsync(new Permission("CanAdd", "Add new page content"));
await permissionService.AddAsync(new Permission("CanEdit", "Edit existing page content"));
await permissionService.AddAsync(new Permission("CanDelete", "Delete page content"));
}
private async Task AddPermissions(DataContext context)
{
var permissionService = new PermissionService(context);
List<Task> permissionRequests = new List<Task>();
permissionRequests.Add(permissionService.AddAsync(new Permission("CanView", "View company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add and view company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit and view company")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete and view company record")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new pages")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdite", "Edit existing pages")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete a page")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new page content")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit existing page content")));
permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete page content")));
await Task.WhenAll(permissionRequests);
}
Task.Factory.StartNew(() => new Permission("CanView", "View company"));
Task.Factory.StartNew(() => new Permission("CanAdd", "Add and view company"));
...