c# - 为什么这么慢,.net任务嵌套子任务

标签 c# asp.net .net asp.net-web-api async-await

我创建了一个 asp.net webapi 测试应用程序,这是我的测试代码:

当我使用 result = index.ToString() + this.getresult().Result; 时,响应时间为 2 秒。如果我使用 Thread.Sleep(100); result = index.ToString();,只需要200ms。

public class HomeController : Controller
{
    public string Test()
    {
        var listName = new List<int>();

        for (int i = 0; i < 100; i++)
        {
            listName.Add(i);
        }

        var response = Task.WhenAll(listName.Select(sendrequest)).Result;

        return string.Join(",", response);
    }

    public async Task<string> sendrequest(int index)
    {
        return await Task.Factory.StartNew(() =>
        {
            string result = string.Empty;

            try
            {
                Thread.Sleep(100); result = index.ToString();
                //result = index.ToString() + this.getresult().Result;
            }
            catch (Exception ex)
            {
                System.IO.File.AppendAllText("D:\\WebService\\FelixTest\\log.txt",ex.ToString());
            }

            return result;

        }).ConfigureAwait(false);
    }

    public async Task<string> getresult()
    {
        await Task.Delay(100);

        return "OK";
    }
}

最佳答案

我认为您正在遭受 ThreadPool 线程饥饿的困扰。问题出在你注释掉的那一行

//result = index.ToString() + this.getresult().Result;

通过访问 Task.Result 属性,您将在 getresult()< 返回的 Task 上引起 Wait/ 方法。 Wait操作会阻塞当前线程执行,这意味着下一个Task必须安排在另一个线程上等等。当您启动 100 个任务时,所有这些任务都会阻塞,ThreadPool 将尝试启动新的托管线程来满足需求,这是一个耗时的过程。

我会重新组织您的代码,以便除了一个顶级 Test 方法之外的所有内容都是异步的。在这个例子中,我不确定为什么你需要 Task.Factory.StartNew() 因为任务已经(至少部分地)并行运行,因为它们使用异步等待图案。也许您的真实示例需要在后台线程上安排任务?如果您不需要使用 Factory.StartNew(),我建议您像这样重写 sendrequest:-

public async Task<string> sendrequest(int index)
{
    string result = string.Empty;
    try
    {
        result = index.ToString() + await this.getresult();
    }
    catch (Exception ex)
    {
        System.IO.File.AppendAllText("D:\\WebService\\FelixTest\\log.txt",ex.ToString());
    }

    return result;
}

如果你确实需要使用 Factory.StartNew() 你仍然可以实现同样的事情,但是你传递给 StartNew 的委托(delegate)应该被标记为 async

关于c# - 为什么这么慢,.net任务嵌套子任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40418647/

相关文章:

c# - 在 Windows 10 中部署 Windows Phone 8.1 应用程序时找不到 IpOverUsbSvc

c# - 基于其他表单输入和验证显示/隐藏表单元素的最佳方法?

c# - 如何更新Web.config以通过C#通过电子邮件发送错误?

.net - SQLite中uniqueidentifier中的乱码文本

c# - 如何获取所选幻灯片的ID

.net - 如何修复 Unix LocalMachine X509Store 仅限于 Root 和 CertificateAuthority 存储错误

c# - 如何将 int 转换为 double?

asp.net - Cookie和子域

asp.net - WinDBG - 不包括符号路径

c# - 如何基于默认的 DataGrid 样式创建样式?