加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 为什么运行一百个异步任务需要比运行一百个线程更长的时间

发布时间:2020-12-15 06:49:47 所属栏目:百科 来源:网络整理
导读:为什么运行一百个异步任务需要比运行一百个线程更长的时间? 我有以下测试类: public class AsyncTests{ public void TestMethod1() { var tasks = new ListTask(); for (var i = 0; i 100; i++) { var task = new Task(Action); tasks.Add(task); task.Sta
为什么运行一百个异步任务需要比运行一百个线程更长的时间?

我有以下测试类:

public class AsyncTests
{

    public void TestMethod1()
    {
        var tasks = new List<Task>();

        for (var i = 0; i < 100; i++)
        {
            var task = new Task(Action);
            tasks.Add(task);
            task.Start();
        }

        Task.WaitAll(tasks.ToArray());            
    }


    public void TestMethod2()
    {
        var threads = new List<Thread>();

        for (var i = 0; i < 100; i++)
        {
            var thread = new Thread(Action);
            threads.Add(thread);
            thread.Start();
        }

        foreach (var thread in threads)
        {
            thread.Join();
        }
    }

    private void Action()
    {
        var task1 = LongRunningOperationAsync();
        var task2 = LongRunningOperationAsync();
        var task3 = LongRunningOperationAsync();
        var task4 = LongRunningOperationAsync();
        var task5 = LongRunningOperationAsync();

        Task[] tasks = {task1,task2,task3,task4,task5};
        Task.WaitAll(tasks);
    }

    public async Task<int> LongRunningOperationAsync()
    {
        var sw = Stopwatch.StartNew();

        await Task.Delay(500);

        Debug.WriteLine("Completed at {0},took {1}ms",DateTime.Now,sw.Elapsed.TotalMilliseconds);

        return 1;
    }
}

尽可能地告诉我们,TestMethod1和TestMethod2应该完全一样.一个使用TPL,两个使用普通的香草线程.一个需要1:30分钟,两次需要0.54秒.

为什么?

解决方法

Action方法正在使用Task.WaitAll(任务)阻止.当使用任务默认情况下,ThreadPool将被用于执行,这意味着您正在阻止共享的ThreadPool线程.

尝试以下内容,您将看到相同的效果:

添加一个非阻塞的Action实现,我们称之为ActionAsync

private Task ActionAsync()
{
    var task1 = LongRunningOperationAsync();
    var task2 = LongRunningOperationAsync();
    var task3 = LongRunningOperationAsync();
    var task4 = LongRunningOperationAsync();
    var task5 = LongRunningOperationAsync();

    Task[] tasks = {task1,task5};
    return Task.WhenAll(tasks);
}

>修改TestMethod1以正确处理新的任务返回的ActionAsync方法

public void TestMethod1()
{
    var tasks = new List<Task>();

    for (var i = 0; i < 100; i++)
    {
        tasks.Add(Task.Run(new Func<Task>(ActionAsync)));
    }

    Task.WaitAll(tasks.ToArray());            
}

你的性能很慢的原因是因为ThreadPool会“慢慢地”产生新的线程,如果你要阻止它可用的几个线程,你会遇到明显的减速.这就是为什么ThreadPool仅用于运行短任务的原因.

如果您打算使用Task运行长时间阻塞操作,那么在创建Task实例时,请确保使用TaskCreationOptions.LongRunning(这将创建一个新的底层Thread而不是使用ThreadPool).

ThreadPool的一些进一步证据是问题,以下也可以减轻你的问题(不要使用这个):

ThreadPool.SetMinThreads(500,500);

这表明新的ThreadPool线程的“慢”产生导致您的瓶颈.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读