c# - c#什么时候需要async和await?

标签 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>(user).State = EntityState.Added;

    await _context.SaveChangesAsync();
}

没有它就这样

public Task CreateAsync(User user)
{
    if (_context.Entry<User>(user).State == EntityState.Detached)
    {
        _context.Set<User>().Add(user);
    }

    _context.Entry<User>(user).State = EntityState.Added;

    return _context.SaveChangesAsync();
}

两者都编译得很好。我总是添加 async 和 await 关键字,想知道我是否做错了并在不需要时编写它们?

编辑:

如果您实际上要返回一个值,应该使用 async/await 关键字编写还是不使用。这是带有关键字的版本

public async Task<User> 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();

    return user;
}

还有一个例子

public Task<User> FindByIdAsync(long userId)
{
    return _context.Users.FindAsync(userId);
}

public async Task<User> FindByIdAsync(long userId)
{
    return await _context.Users.FindAsync(userId);
}

编辑 2

到目前为止,答案非常好,但还有最后一个例子。由于我有异步调用,我将如何处理从 1 种方法调用多个异步函数。这是我所拥有的示例,但我不知道它是否正确。在所有 AddAsync 方法完成之前,我不希望该方法退出。这是正确的吗

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

最佳答案

恕我直言,如果您希望 SaveChangesAsync 操作在方法返回时完成,或者您需要对异步操作。在这种情况下,您不会对其进行任何操作,因此最好不要使用异步方法并避免生成 state machine withing the method ,从而提高代码效率。

关于您的第二次编辑,您是正确的。虽然该方法将在遇到第一个 await 时立即返回,但所有其他等待的语句将在线程池中一个接一个地执行,然后任务的结果将被更新。因此,如果您 await AddPermissions 除非抛出异常,否则该语句只会在所有内部 permissionService.AddAsync 调用完成后完成。

如有必要,也可以并行执行 permissionService.AddAsync 调用,方法是将返回的任务存储在列表中,然后等待 Task.WhenAll

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);
}

因此每次调用 permissionService.AddAsync 都会启动请求并将相应的任务添加到列表中。启动所有请求后,您可以使用 await Task.WhenAll await 所有请求完成,这将等到它们全部完成或返回错误。抛出的任何异常都将存储在从 Task.WhenAll 返回的任务中。等待该任务将重新抛出第一个异常,但您可以使用包含 AggregatedException 又包含所有抛出的异常。

关于c# - c#什么时候需要async和await?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27032631/

相关文章:

c# - 使用 ServiceBus SubscriptionClient 时出现 RenewLock 错误

c# - 通用类型参数协变和多接口(interface)实现

.net - 简单的NEST搜索不返回结果

asp.net - 托管 ASP.NET 应用程序的硬盘空间对网站的性能有影响吗?

c# - ManualResetEvent WaitOne(timeout) 提前返回。任何想法为什么?

c# - 为什么枚举需要显式转换为 int 类型?

c# - 如何为带有 "out"参数的私有(private)函数编写 C# 测试用例?

c# - 正则表达式以任意顺序捕获组

javascript - 如何将选择列表选项发布到 MVC 操作方法?

c# - 我的类库类中的 StringBuilder html 表