简体   繁体   English

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

[英]why is so slow, .net task nest sub task

I create an asp.net webapi test application, here is my test code: 我创建了一个asp.net webapi测试应用程序,这是我的测试代码:

When I use the result = index.ToString() + this.getresult().Result; 当我使用result = index.ToString() + this.getresult().Result; , the response time is 2s. ,响应时间是2s。 If I use Thread.Sleep(100); result = index.ToString(); 如果我使用Thread.Sleep(100); result = index.ToString(); Thread.Sleep(100); result = index.ToString(); , it only needs 200ms. ,它只需要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";
    }
}

I think you are suffering from ThreadPool thread starvation. 我认为你正在遭受ThreadPool线程饥饿。 The problem lies in the line you have commented-out 问题出在你已注释掉的那一行

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

By accessing the Task.Result property, you are causing a Wait on the Task returned from the getresult() method. 通过访问Task.Result属性,您将导致从getresult()方法返回的TaskWait The Wait operation blocks the current thread from executing, which means that the next Task must be scheduled on another thread and so on. Wait操作阻止当前线程执行,这意味着必须在另一个线程上安排下一个Task,依此类推。 As you are starting 100 tasks all of which will block, the ThreadPool will attempt to start new managed threads to satisfy the demand, and this is a time-consuming process. 当您启动所有将阻止的100个任务时,ThreadPool将尝试启动新的托管线程以满足需求,这是一个耗时的过程。

I would reorganise your code so that everything is asynchronous except for the one top-level Test method. 我会重新组织你的代码,以便一切都是异步的,除了一个顶级的Test方法。 In this example I'm not sure why you need Task.Factory.StartNew() as the tasks are already run (at least partially) in parallel by virtue of the fact that they use the async-await pattern. 在这个例子中,我不确定为什么你需要Task.Factory.StartNew()因为任务已经(至少部分地)并行运行,因为它们使用async-await模式。 Perhaps your real-life example requires the tasks to be scheduled on a background thread? 也许您的真实示例需要在后台线程上安排任务? If you don't need to use Factory.StartNew() I'd suggest rewriting sendrequest like this:- 如果您不需要使用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;
}

If you do need to use Factory.StartNew() you can still achieve the same thing, but the delegate you pass to StartNew should be marked async . 如果确实需要使用Factory.StartNew()您仍然可以实现相同的功能,但是传递给StartNew的委托应该标记为async

According to your description the difference is of 1800 milliseconds. 根据您的描述,差异是1800毫秒。 You have a delay of 100 milliseconds in getresult . getresult你有100毫秒的延迟。 If we subtract that, the difference is of 1700 milliseconds. 如果我们减去它,差值是1700毫秒。 A string concatenation with "OK" does not explain that. 带有"OK"字符串连接并不能解释这一点。 As a result, you probably use a loop and the delays of 100 milliseconds in getresult add up to a significant wait. 因此,您可能会使用循环,并且getresult的延迟为100毫秒getresult增加一个重要的等待时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM