C#中对任务和线程并行运行,测试其执行时间

为了提高程序的的性能,减少流程的时间时,我们总是会考虑将流程分成多个部分,并在同一时刻执行它。这就是并行性,那么在并行中线程和任务哪个更好呢?

1.使用线程

在此示例中,我们将每个线程添加到一个列表中,在最后一个示例中,我们正在等待所有线程完成。此外,我们还使用锁将变量计数放在线程安全中,并使用 anyObject 辅助工具来确保锁 (anyObject) 中的所有代码保持安全而不会损坏最终结果。在该实现中花费的执行时间为 1 秒,与下面的其他实现相比更好。
    class Program
    {
        static int count = 0;
        static object anyObject = new object();
        static Stopwatch sw = new Stopwatch();
        static void Main(string[] args)
        {


            sw.Restart();
            UseThreads();
            sw.Stop();
            Console.WriteLine(sw.Elapsed.Seconds);
            Console.ReadKey();
        }


        static void UseThreads()
        {
            var threads = new List<Thread>();

            for (int i = 0; i < 100; i++)
            {
                var thread = new Thread(() =>
                {
                    AnyMethod();
                    lock (anyObject) count++;
                });
                thread.Start();
                threads.Add(thread);
            }

            threads.ForEach(t => t.Join());
        }
        static void AnyMethod() => Thread.Sleep(1000);
    }
//Time spent: 1 seconds

2.使用任务

在这个例子中,如何给出上面的例子,我们将每个任务添加到一个列表中,在最后,我们正在等待所有任务完成。此外,我们还使用锁将变量计数放在线程安全中,并使用 anyObject 辅助工具来确保锁 (anyObject) 中的所有代码保持安全而不会损坏最终结果。在该实现中花费的执行时间为 18 秒,与第一次相比,我们可以看到多 17 秒的差异。到目前为止,这不是最好的选择。
void UseTasks()
{
    var tasks = new List<Task>();

    for (int i = 0; i < 100; i++)
    {
        var task = new Task(() =>
        {
            AnyMethod();
            lock (anyObject) count++;
        });

        task.Start();
        tasks.Add(task);
    }

    Task.WaitAll(tasks.ToArray());
}
//Time spent: 18 seconds

3.使用 Parallel for

在这种情况下,收益是减少线代码,它贡献了干净的代码。但是在该实现中花费的执行时间为 15 秒。

void UseParallelFor()
{
    Parallel.For(0, 100, (i) =>
    {
        AnyMethod();
        lock (anyObject) count++;
    });
}
//Time spent: 15 seconds

4.使用 Parallel ForEach

按照下面的示例,区别在于遵循 ForEach 的相同想法,并且花费的执行时间相同为 15 秒。

void UseParallelForEach()
{
    Parallel.ForEach(new int[100], (i) =>
    {
        AnyMethod();
        lock (anyObject) count++;
    });
}
//Time spent: 15 seconds

5.使用信号量与线程

使用SemaphoreSlim 中使用的线程数。其中的参数(Environment.ProcessorCount),获取处理器中包含的逻辑处理器的数量。例如:如果您的处理器有 8 个逻辑处理器,您将有 8 个线程,但如果您想要的线程数多于处理器的逻辑处理器数量,则可能会失去每个线程的处理能力。通过此实现,我们在执行时间上花费了 13 秒。

void UseSemaphoreWithThreads()
{
    var semaphoreSlim = new SemaphoreSlim(Environment.ProcessorCount);
    var threads = new List<Thread>();

    for (int i = 0; i < 100; i++)
    {
        var thread = new Thread(() =>
        {
            semaphoreSlim.Wait();

            AnyMethod();
            lock (anyObject) count++;

            semaphoreSlim.Release();
        });

        thread.Start();
        threads.Add(thread);
    }

    threads.ForEach(t => t.Join());
}
//Time spent: 25 seconds

总结

	上述例子中不同的电脑的执行时间不一致,根据上述执行时间的结果,更好的性能是使用 Threads 在 1 秒内执行,但更好的实现是使用 Parallel 的示例,代码行更少,代码更干净。
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值