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

前端之家收集整理的这篇文章主要介绍了c# – 为什么运行一百个异步任务需要比运行一百个线程更长的时间?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
为什么运行一百个异步任务需要比运行一百个线程更长的时间?

我有以下测试类:

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线程的“慢”产生导致您的瓶颈.

原文链接:https://www.f2er.com/csharp/94483.html

猜你在找的C#相关文章