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

本文关键字:任务 嵌套 子任务 net 为什么 | 更新日期: 2023-09-27 18:16:39

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

当我使用result = index.ToString() + this.getresult().Result;时,响应时间为2s。如果我使用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";
    }
}

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

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

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

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

我会重新组织你的代码,使一切都是异步的,除了一个顶级Test方法。在这个例子中,我不确定为什么需要Task.Factory.StartNew(),因为任务已经并行运行(至少部分),因为它们使用async-await模式。也许您的实际示例需要将任务安排在后台线程上?如果你不需要使用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的委托应该标记为async

根据您的描述,差值为1800毫秒。在getresult中有100毫秒的延迟。如果我们减去这个,差是1700毫秒。与"OK"的字符串连接不能解释这一点。因此,您可能会使用一个循环,getresult中100毫秒的延迟加起来就是一个很长的等待时间。