【问题标题】:nested async methods and thread pool Asp.Net嵌套异步方法和线程池 Asp.Net
【发布时间】:2015-09-24 23:02:06
【问题描述】:

我正在构建一个async Web Api,在阅读了一些关于async/await 的文章后,我认为我做错了什么。

这是我的实际代码:

public async Task<IHttpActionResult> GetAccount(int id)
{
    var i = await GetInstanceIdAsync(User, _db); //grabs a thread
    ...
}

public async static Task<int> GetInstanceIdAsync(IPrincipal user, Entities db)
{
    var userManager = 
         new UserManager<ControliUser>(new UserStore<ControliUser>(db));
    //next line grabs another thread but since it was called from an await
    //it holds 2 threads, am I correct?
    var u = await userManager.FindByNameAsync(user.Identity.Name);
    return u == null ? 0 : u.InstanceId ?? 0;
}

所以我的第一个问题是,这会消耗 2 个线程吗?

如果答案是肯定的,那么我做了这个扩展方法来防止这种情况发生。

public static Task<int?> InstanceIdAsync(this Entities db, IPrincipal user)
{
    var userManager = new UserManager<ControliUser>(new UserStore<ControliUser>(db));
    return userManager.FindByNameAsync(user.Identity.Name).ContinueWith(t =>
    {
        if (t.IsCompleted && t.Result != null)
            return t.Result.InstanceId;
        return null;
    });
}

我认为这种方法只会消耗 1 个线程并减少开销,因为它节省了 async 方法

我说的对吗?

【问题讨论】:

  • Oldie but goodie - Asynchronous Programming in C# 5.0 part two Eric Lippert - “异步方法的全部意义在于您尽可能地留在当前线程上”
  • await 主要是一种花哨的方式来表达 ContinueWith。

标签: c# asp.net asynchronous async-await


【解决方案1】:

所以我的第一个问题是,这会消耗 2 个线程吗?

没有。使用 async-await 不会产生任何额外的线程使用。相反,它在异步操作正在进行时释放线程。这意味着线程将一直使用到调用FindByNameAsync,然后将被释放,只有在该操作完成后才能恢复。然后,它将在任意线程池线程上恢复操作(第一个 await 之后的代码),同时保留请求上下文。

我认为这种方法只会消耗1个线程并减少开销 因为它保存了一个异步方法

首先,这在 WebAPI 中不起作用。问题是只有在第一个任务完成后才会执行延续。反过来,这将向同步上下文发出信号,表明正在进行已完成的 IO 操作,并将导致异常。

如前所述,异步方法不会生成任何线程使用,它所做的只是创建一个 状态机,以便它可以调用您的延续方法(第一个 await 之后的任何调用)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2012-07-31
    • 2020-08-05
    • 2010-12-22
    相关资源
    最近更新 更多