Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在c#中何时需要异步和等待?_C#_Asp.net_.net_Asynchronous - Fatal编程技术网

在c#中何时需要异步和等待?

在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&

正如标题所说。我想知道我是否正在写异步,并在不需要时等待它

我见过这样的带有async标记的方法

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"));
...