首页 虚拟现实

C# 高并发利器:从 Thread 到 async/await 的进阶之路

分类:虚拟现实
字数: (6971)
阅读: (5801)
内容摘要:C# 高并发利器:从 Thread 到 async/await 的进阶之路,

在构建高性能 C# 应用时,C#多线程全家桶 是开发者必须掌握的关键技能。尤其在高并发场景下,如 Web API 接口服务,数据库连接池,消息队列处理等,合理利用多线程可以显著提升系统吞吐量和响应速度。本文将深入探讨从最基础的 Thread 到现代的 async/await 的各种多线程技术,助你打造更健壮、更高效的应用程序。

线程(Thread):最基础的多线程

Thread 类是 C# 中实现多线程的基础。直接操作线程能够提供最大的灵活性,但也伴随着更高的复杂性和风险。例如,我们需要手动管理线程的生命周期,处理线程同步问题,以及避免死锁等情况。

C# 高并发利器:从 Thread 到 async/await 的进阶之路

创建和启动线程

using System;
using System.Threading;

public class ThreadExample
{
    public static void Main(string[] args)
    {
        // 创建一个新的线程
        Thread thread = new Thread(new ThreadStart(DoWork));

        // 启动线程
        thread.Start();

        Console.WriteLine("Main thread continues to execute...");
        Console.ReadKey();
    }

    static void DoWork()
    {
        Console.WriteLine("Thread started...");
        Thread.Sleep(2000); // 模拟耗时操作
        Console.WriteLine("Thread completed...");
    }
}

线程同步:锁(Lock)和互斥量(Mutex)

当多个线程访问共享资源时,必须进行同步,以避免数据竞争和不一致性。lock 关键字和 Mutex 类是常用的同步工具。

C# 高并发利器:从 Thread 到 async/await 的进阶之路
using System;
using System.Threading;

public class LockExample
{
    private static readonly object lockObject = new object();
    private static int counter = 0;

    public static void Main(string[] args)
    {
        Thread[] threads = new Thread[5];

        for (int i = 0; i < 5; i++)
        {
            threads[i] = new Thread(IncrementCounter);
            threads[i].Start();
        }

        foreach (Thread thread in threads)
        {
            thread.Join(); // 等待所有线程完成
        }

        Console.WriteLine("Counter value: " + counter);
        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        for (int i = 0; i < 1000; i++)
        {
            lock (lockObject) // 使用 lock 保护共享资源
            {
                counter++;
            }
        }
    }
}

任务(Task):更高级的抽象

Task 类提供了比 Thread 更高级的抽象,简化了多线程编程。Task 可以返回结果,并且更容易进行组合和控制。

C# 高并发利器:从 Thread 到 async/await 的进阶之路

创建和启动任务

using System;
using System.Threading.Tasks;

public class TaskExample
{
    public static void Main(string[] args)
    {
        // 创建并启动一个任务
        Task<int> task = Task.Run(() => {
            Console.WriteLine("Task started...");
            Task.Delay(2000).Wait(); // 模拟耗时操作
            Console.WriteLine("Task completed...");
            return 42; // 返回结果
        });

        Console.WriteLine("Main thread continues to execute...");

        // 等待任务完成并获取结果
        task.Wait();
        Console.WriteLine("Task result: " + task.Result);
        Console.ReadKey();
    }
}

任务并行库(TPL)

TPL 提供了更强大的并行编程能力,例如 Parallel.ForParallel.ForEach,可以自动将循环任务分配到多个线程上执行,充分利用多核 CPU 的优势。

C# 高并发利器:从 Thread 到 async/await 的进阶之路
using System;
using System.Threading.Tasks;

public class ParallelExample
{
    public static void Main(string[] args)
    {
        int[] numbers = new int[100];
        for (int i = 0; i < 100; i++)
        {
            numbers[i] = i + 1;
        }

        // 使用 Parallel.ForEach 并行处理数组元素
        Parallel.ForEach(numbers, number => {
            Console.WriteLine("Processing number: " + number + " on thread: " + Thread.CurrentThread.ManagedThreadId);
            Task.Delay(100).Wait(); // 模拟耗时操作
        });

        Console.WriteLine("Parallel processing completed.");
        Console.ReadKey();
    }
}

异步编程(async/await):提升响应性的利器

async/await 是 C# 中实现异步编程的强大工具。它能够让开发者以同步的方式编写异步代码,避免了回调地狱,提高了代码的可读性和可维护性。在 Web API 开发中,经常需要处理 I/O 密集型操作,例如访问数据库、调用外部服务等,使用 async/await 可以避免阻塞主线程,提高应用的响应性。这与 Nginx 反向代理和负载均衡的设计理念不谋而合,都是为了提升系统并发连接数和吞吐量。

异步方法

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

public class AsyncAwaitExample
{
    public static async Task Main(string[] args)
    {
        Console.WriteLine("Starting...");
        string result = await DownloadDataAsync("https://www.example.com");
        Console.WriteLine("Downloaded: " + result.Substring(0, 100) + "..."); // 截取前 100 个字符
        Console.WriteLine("Completed.");
        Console.ReadKey();
    }

    static async Task<string> DownloadDataAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            // 异步下载数据
            HttpResponseMessage response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode(); // 检查状态码
            string content = await response.Content.ReadAsStringAsync();
            return content;
        }
    }
}

实战避坑:ConfigureAwait(false)

在使用 async/await 时,一个常见的坑是关于 ConfigureAwait(false) 的使用。默认情况下,await 会尝试在原始上下文中恢复执行,这在 UI 线程中是很重要的。但在库代码中,通常不需要恢复到原始上下文,使用 ConfigureAwait(false) 可以避免不必要的上下文切换,提高性能,并防止死锁。

public async Task<string> GetDataAsync()
{
    // 使用 ConfigureAwait(false) 避免上下文切换
    string result = await LongRunningOperationAsync().ConfigureAwait(false);
    return result;
}

private async Task<string> LongRunningOperationAsync()
{
    await Task.Delay(1000);
    return "Data";
}

选择合适的多线程技术

选择哪种多线程技术取决于具体的应用场景和需求:

  • Thread: 提供最大的灵活性,但需要手动管理线程的生命周期和同步,适用于对线程控制要求较高的场景。
  • Task: 更高级的抽象,简化了多线程编程,适用于需要返回结果、组合和控制的场景。
  • TPL: 提供了强大的并行编程能力,适用于计算密集型任务。
  • async/await: 提高了应用的响应性,适用于 I/O 密集型任务。

掌握 C#多线程全家桶 中的各种技术,能够帮助你构建更高效、更健壮的 C# 应用。在实际开发中,要根据具体的场景选择合适的技术,并注意线程同步和避免死锁等问题,才能充分发挥多线程的优势。

C# 高并发利器:从 Thread 到 async/await 的进阶之路

转载请注明出处: 键盘上的咸鱼

本文的链接地址: http://m.acea2.store/blog/708155.SHTML

本文最后 发布于2026-04-14 21:44:23,已经过了13天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 真香警告 3 天前
    TPL 那部分如果能再深入一些就更好了,比如 ParallelOptions 的使用。
  • 橘子汽水 4 天前
    写的不错,对 Thread、Task 和 async/await 做了比较清晰的对比,赞一个!
  • 太阳当空照 5 天前
    TPL 那部分如果能再深入一些就更好了,比如 ParallelOptions 的使用。
  • 榴莲控 2 天前
    感觉 async/await 还是有点难理解,有没有更简单点的例子?
  • 工具人 6 天前
    关于 ConfigureAwait(false) 的解释很到位,之前一直不太理解,现在明白了。