多任务减慢 [英] Multiple Tasks slows down

查看:112
本文介绍了多任务减慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

中的代码:

 静态无效DOIT(字符串名称)
{
Console.WriteLine( 你好{0} | {1},名称,Thread.CurrentThread.ManagedThreadID);
Thread.sleep代码(5000);
Console.WriteLine(再见{0} | {1},名称,Thread.CurrentThread.ManagedThreadID);
}

静态无效的主要()
{
Task.Factory.StartNew(()=> DOIT(1));
Task.Factory.StartNew(()=> DOIT(二));
Task.Factory.StartNew(()=> DOIT(三国));
Task.Factory.StartNew(()=> DOIT(四));
Task.Factory.StartNew(()=> DOIT(五));
Task.Factory.StartNew(()=> DOIT(六个一));
Task.Factory.StartNew(()=> DOIT(七));
Task.Factory.StartNew(()=> DOIT(八));
Task.Factory.StartNew(()=> DOIT(九));
Task.Factory.StartNew(()=> DOIT(十大));

Console.ReadKey();
}



为什么它可以精确立即开始前3个任务,但随后需要5-10sec任务4开局,任务4开始后,再前任务5开工等需要5-10sec。难道这就是做事的GC?可能有人请澄清发生了什么?


解决方案

为什么它可以很好的开端前3个任务马上,但它需要5-10sec任务4开局,任务4开始后,再前任务5开工等需要5-10sec。难道这就是做事的GC?可能有人请澄清发生了什么?




默认情况下,第一次运行这一点,线程池使用工作线程的最小数量进行分配。第4个任务调度完成后,线程池会坡道,以处理更多的随着时间的推移,这就是为什么你看到的延迟。



在我的系统(其中有8个内核),前8个是instantanteous,那么接下来的两年后开始了一秒钟。



在你的情况,如果你运行测试两次,在第二的时候,线程都将立即启动。这是因为,在第一次运行后,线程池应该有足够的工人来安排这项权利了。



请尝试以下方法在行动中看到此行为。如果离开SetM​​inThreads立即拨打到位,这些将全部日程。如果你把它注释掉,你会看到,在第一时间,它需要一段时间,但通过第二次(只要你等待线程完成),线程就会立即运行。

 静态无效DOIT(字符串名称)
{
Console.WriteLine(你好{0} | {1} - {2} ,名称,Thread.CurrentThread.ManagedThreadId,DateTime.Now);
Thread.sleep代码(5000);
Console.WriteLine(再见{0} | {1} - {2},名称,Thread.CurrentThread.ManagedThreadId,DateTime.Now);
}

静态无效的主要()
{
INT workerThreads,完整的;
ThreadPool.GetMinThreads(出workerThreads,出完整);

Console.WriteLine(workerThreads);

//注释掉此行看到其中的差别...
//与此注释掉,第二次迭代将立即
ThreadPool.SetMinThreads(100,完成) ;

行动RUN =()=>
{
的for(int i = 0; I< 20; ++ I)
{
INT TMP = I;
Task.Factory.StartNew(()=> DOIT(tmp.ToString()));
}
};

的run();
Console.WriteLine(按任意键再次运行...);
Console.ReadKey();

的run();

Console.WriteLine(按任意键退出...);
Console.ReadKey();
}

请注意,这种行为实际上有一点与TPL作为一个整体做的事 - 它更使用默认的的TaskScheduler 刚刚通过关闭任务的线程池。如果要设置这些线程与在 StartNew()通话 LongRunning 提示,例如,他们' D ALL立即启动(因为默认调度程序将设置一个新的,专门的线程并立即执行)。


The code:

static void DoIt(string name)
{
    Console.WriteLine("Hello {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
    Thread.Sleep(5000);
    Console.WriteLine("Bye {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
}

static void Main()
{
    Task.Factory.StartNew(() => DoIt("One"));
    Task.Factory.StartNew(() => DoIt("Two"));
    Task.Factory.StartNew(() => DoIt("Three"));
    Task.Factory.StartNew(() => DoIt("Four"));
    Task.Factory.StartNew(() => DoIt("Five"));
    Task.Factory.StartNew(() => DoIt("Six"));
    Task.Factory.StartNew(() => DoIt("Seven"));
    Task.Factory.StartNew(() => DoIt("Eight"));
    Task.Factory.StartNew(() => DoIt("Nine"));
    Task.Factory.StartNew(() => DoIt("Ten"));

    Console.ReadKey();
}

How come that it can fine start the first 3 Tasks immediately, but then it takes 5-10sec for Task 4 to start, and after Task 4 have started, then it takes 5-10sec before Task 5 starts and so on. Is it the GC thats doing something? Could someone please clarify whats happening?

解决方案

How come that it can fine start the first 3 Tasks immediately, but then it takes 5-10sec for Task 4 to start, and after Task 4 have started, then it takes 5-10sec before Task 5 starts and so on. Is it the GC thats doing something? Could someone please clarify whats happening?

By default, the first time you run this, the ThreadPool is allocated using the minimum number of worker threads. After the first 4 tasks are scheduled, the threadpool will "ramp up" to handle more over time, which is why you see the delay.

On my system (which has 8 cores), the first 8 are instantanteous, then the next two start up one second later.

In your case, if you run your test two times, the second time, the threads will all start up immediately. This is because, after the first run, the ThreadPool should have enough workers to schedule this right away.

Try the following to see this behavior in action. If you leave the SetMinThreads call in place, these will all schedule immediately. If you comment it out, you'll see that, the first time, it takes a while, but the second time through (provided you wait for the threads to complete), the threads will run immediately.

static void DoIt(string name)
{
    Console.WriteLine("Hello {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
    Thread.Sleep(5000);
    Console.WriteLine("Bye {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}

static void Main()
{
    int workerThreads, complete;
    ThreadPool.GetMinThreads(out workerThreads, out complete);

    Console.WriteLine(workerThreads);

    // Comment out this line to see the difference...
    // WIth this commented out, the second iteration will be immediate
    ThreadPool.SetMinThreads(100, complete);

    Action run = () =>
        {
            for (int i = 0; i < 20; ++i)
            {
                int tmp = i;
                Task.Factory.StartNew(() => DoIt(tmp.ToString()));
            }
        };

    run();
    Console.WriteLine("Press a key to run again...");
    Console.ReadKey();

    run();

    Console.WriteLine("Press a key to exit...");
    Console.ReadKey();
}

Note that this behavior actually has little to do with the TPL as a whole - it's more the default TaskScheduler used which just passes off the tasks to the ThreadPool. If you were to set these threads up with the LongRunning hint in your StartNew() call, for example, they'd all start immediately (since the default scheduler will setup a new, dedicated thread and execute it immediately).

这篇关于多任务减慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆