跳转到内容

C Sharp 任务并行

来自代码酷

C#任务并行[编辑 | 编辑源代码]

任务并行(Task Parallelism)是C#并发编程中的核心概念之一,它允许开发者将工作分解为多个独立的任务,并利用多核处理器的能力并行执行这些任务,从而提高应用程序的性能和响应能力。在.NET中,任务并行主要通过System.Threading.Tasks命名空间中的TaskParallel类来实现。

介绍[编辑 | 编辑源代码]

任务并行的核心思想是将一个大问题分解为多个小任务,并让这些任务在不同的线程上同时运行。与传统的线程编程相比,任务并行提供了更高层次的抽象,简化了并行代码的编写和管理。任务并行适用于计算密集型操作(如数据处理、图像渲染)和I/O密集型操作(如文件读写、网络请求)。

在C#中,任务并行主要通过以下方式实现:

  • Task类:表示一个异步操作,可以手动创建和管理。
  • Parallel类:提供静态方法(如Parallel.ForParallel.ForEach)简化数据并行操作。
  • async/await:用于编写异步代码,但通常归类为异步编程而非严格的任务并行。

基本用法[编辑 | 编辑源代码]

使用Task类[编辑 | 编辑源代码]

以下是一个简单的示例,展示如何使用Task类创建和运行任务:

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // 创建一个任务并启动
        Task task = Task.Run(() => 
        {
            Console.WriteLine("任务正在运行...");
        });

        // 等待任务完成
        task.Wait();
        Console.WriteLine("任务完成。");
    }
}

输出:

任务正在运行...
任务完成。

使用Parallel.For[编辑 | 编辑源代码]

Parallel.For方法允许并行执行循环迭代。以下示例计算1到10的平方:

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Parallel.For(1, 11, i => 
        {
            Console.WriteLine($"数字 {i} 的平方是 {i * i}");
        });
    }
}

输出(顺序可能不同):

数字 1 的平方是 1
数字 4 的平方是 16
数字 2 的平方是 4
数字 5 的平方是 25
数字 3 的平方是 9
数字 6 的平方是 36
数字 7 的平方是 49
数字 8 的平方是 64
数字 9 的平方是 81
数字 10 的平方是 100

任务并行与数据并行[编辑 | 编辑源代码]

任务并行通常与数据并行(Data Parallelism)结合使用。数据并行是指对数据集中的每个元素执行相同的操作,而任务并行是指执行多个独立的任务。以下是一个结合两者的示例:

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        // 数据并行:计算数组元素的平方
        int[] numbers = { 1, 2, 3, 4, 5 };
        Parallel.ForEach(numbers, num => 
        {
            Console.WriteLine($"{num} 的平方是 {num * num}");
        });

        // 任务并行:同时执行两个独立任务
        Task task1 = Task.Run(() => Console.WriteLine("任务1完成"));
        Task task2 = Task.Run(() => Console.WriteLine("任务2完成"));
        Task.WaitAll(task1, task2);
    }
}

输出(顺序可能不同):

1 的平方是 1
2 的平方是 4
3 的平方是 9
4 的平方是 16
5 的平方是 25
任务1完成
任务2完成

实际应用案例[编辑 | 编辑源代码]

图像处理[编辑 | 编辑源代码]

假设需要对一批图像进行模糊处理,可以使用任务并行加速:

using System;
using System.IO;
using System.Threading.Tasks;

class ImageProcessor
{
    static void BlurImage(string imagePath)
    {
        // 模拟图像模糊处理
        Console.WriteLine($"正在处理图像: {Path.GetFileName(imagePath)}");
        Task.Delay(1000).Wait(); // 模拟耗时操作
    }

    static void Main()
    {
        string[] images = Directory.GetFiles(@"C:\Images", "*.jpg");
        Parallel.ForEach(images, image => BlurImage(image));
        Console.WriteLine("所有图像处理完成。");
    }
}

并行计算[编辑 | 编辑源代码]

计算π的近似值(蒙特卡洛方法):

using System;
using System.Threading.Tasks;

class MonteCarloPi
{
    static void Main()
    {
        int totalPoints = 1000000;
        int pointsInside = 0;
        object lockObj = new object();

        Parallel.For(0, totalPoints, i => 
        {
            Random rand = new Random(Guid.NewGuid().GetHashCode());
            double x = rand.NextDouble();
            double y = rand.NextDouble();

            if (x * x + y * y <= 1)
            {
                lock (lockObj) { pointsInside++; }
            }
        });

        double pi = 4.0 * pointsInside / totalPoints;
        Console.WriteLine($"π的近似值: {pi}");
    }
}

任务并行的工作原理[编辑 | 编辑源代码]

任务并行在底层使用线程池来管理线程。当创建多个任务时,线程池会根据可用资源动态分配线程。以下是一个简化的任务调度流程:

graph TD A[创建任务] --> B[提交到线程池] B --> C{线程可用?} C -->|是| D[立即执行] C -->|否| E[排队等待] D --> F[任务完成] E --> F

注意事项[编辑 | 编辑源代码]

1. 线程安全:并行任务可能同时访问共享资源,需使用锁(lock)或其他同步机制。 2. 任务取消:使用CancellationToken支持任务取消。 3. 异常处理:使用Task.Exception属性捕获任务中的异常。 4. 避免过度并行化:过多的任务可能导致性能下降。

总结[编辑 | 编辑源代码]

任务并行是C#中实现高性能并发编程的重要工具。通过TaskParallel类,开发者可以轻松地将工作分解为并行任务,充分利用多核处理器的能力。在实际应用中,任务并行广泛用于图像处理、科学计算、Web请求处理等场景。