C# 多线程编程:方法与模式

290 阅读2分钟

C# 多线程编程:方法与模式

引言

在现代软件开发中,多线程编程是一个关键技术,它可以显著提升应用程序的性能和响应能力。C# 提供了多种方式来实现多线程编程,包括使用 Thread 类、ThreadPoolTask 类以及 async/await 模式。此外,生产者-消费者模式是一种常见的多线程编程模式,通常用于处理生产者生成数据,消费者处理数据的场景。本文将详细介绍这些方法和模式。

多线程编程方法

1. 使用 Thread

Thread 类是 .NET 中最基础的线程类,用于创建和控制线程。以下是一个简单的示例:

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        Thread thread = new Thread(new ThreadStart(DoWork));
        thread.Start();
        
        Console.WriteLine("Main thread does some work.");
        
        thread.Join();
        Console.WriteLine("Main thread exits.");
    }

    static void DoWork()
    {
        Console.WriteLine("Background thread does some work.");
    }
}

2. 使用 ThreadPool

ThreadPool 提供了一种简单的方式来使用线程池执行任务,而不需要自己管理线程的创建和销毁。

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        ThreadPool.QueueUserWorkItem(DoWork);
        
        Console.WriteLine("Main thread does some work.");
        
        Thread.Sleep(1000); // 等待后台线程完成
        Console.WriteLine("Main thread exits.");
    }

    static void DoWork(object state)
    {
        Console.WriteLine("Thread pool thread does some work.");
    }
}

3. 使用 Task

Task 类提供了一个基于任务的异步编程模型,可以更轻松地处理复杂的并发和异步操作。

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Task task = Task.Run(() => DoWork());
        
        Console.WriteLine("Main thread does some work.");
        
        await task;
        Console.WriteLine("Main thread exits.");
    }

    static void DoWork()
    {
        Console.WriteLine("Task does some work.");
    }
}

4. 使用 asyncawait

asyncawait 关键字使得异步编程更加简洁和易于阅读,适合处理 I/O 密集型操作。

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Console.WriteLine("Main thread starts work.");
        
        string result = await GetDataAsync();
        
        Console.WriteLine($"Data received: {result}");
        Console.WriteLine("Main thread exits.");
    }

    static async Task<string> GetDataAsync()
    {
        using HttpClient client = new HttpClient();
        string data = await client.GetStringAsync("https://www.example.com");
        return data;
    }
}

5. 使用 Parallel

Parallel 类用于并行执行循环和并行调用。

using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        Parallel.For(0, 10, i =>
        {
            Console.WriteLine($"Parallel task {i} is working.");
        });

        Parallel.Invoke(
            () => Console.WriteLine("First parallel task."),
            () => Console.WriteLine("Second parallel task.")
        );

        Console.WriteLine("Main thread exits.");
    }
}

6. 使用 CancellationToken

CancellationToken 用于取消异步操作。

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

class Program
{
    static async Task Main()
    {
        var cts = new CancellationTokenSource();
        var token = cts.Token;

        var task = Task.Run(() => DoWork(token), token);

        Console.WriteLine("Press Enter to cancel the operation.");
        Console.ReadLine();
        
        cts.Cancel();
        
        try
        {
            await task;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Task was cancelled.");
        }
        
        Console.WriteLine("Main thread exits.");
    }

    static void DoWork(CancellationToken token)
    {
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"Task is working: {i}");
            Thread.Sleep(500);
        }
    }
}

生产者-消费者模式

生产者-消费者模式是一种常见的多线程编程模式,通常用于处理生产者生成数据,消费者处理数据的场景。以下是一个使用 BlockingCollection 实现生产者-消费者模式的示例:

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        BlockingCollection<int> blockingCollection = new BlockingCollection<int>(boundedCapacity: 10);

        Task producer = Task.Run(() =>
        {
            for (int i = 0; i < 20; i++)
            {
                blockingCollection.Add(i);
                Console.WriteLine($"Produced: {i}");
                Thread.Sleep(100); // 模拟生产数据的延迟
            }
            blockingCollection.CompleteAdding();
        });

        Task consumer = Task.Run(() =>
        {
            foreach (var item in blockingCollection.GetConsumingEnumerable())
            {
                Console.WriteLine($"Consumed: {item}");
                Thread.Sleep(150); // 模拟消费数据的延迟
            }
        });

        Task.WaitAll(producer, consumer);
        Console.WriteLine("All tasks completed.");
    }
}

结论

C# 提供了多种方式进行多线程编程,包括使用 Thread 类、ThreadPoolTask 类和 async/await 模式。根据不同的需求,可以选择合适的方法实现多线程。生产者-消费者模式是处理生产和消费数据的常见模式,使用 BlockingCollection 可以轻松实现该模式。在实际应用中,选择合适的多线程编程模式和工具能够显著提高程序的性能和响应能力。