C# 并发模式
介绍
在现代应用程序开发中,并发是一个非常重要的概念。它允许程序同时执行多个任务,从而提高性能和响应能力。C# 提供了多种并发模式,帮助开发者有效地管理多线程和异步操作。本文将介绍 C# 中常见的并发模式,并通过代码示例和实际案例帮助你理解这些概念。
什么是并发模式?
并发模式是指在多线程或异步编程中,用于管理任务执行和资源共享的设计模式。C# 提供了多种并发模式,包括:
- 异步编程模型(APM)
- 基于事件的异步模式(EAP)
- 任务并行库(TPL)
- 异步/等待模式(async/await)
接下来,我们将逐一介绍这些模式。
1. 异步编程模型(APM)
异步编程模型(Asynchronous Programming Model,APM)是 C# 早期的一种并发模式。它使用 BeginXXX
和 EndXXX
方法来启动和结束异步操作。
示例代码
using System;
using System.IO;
class Program
{
static void Main()
{
byte[] buffer = new byte[100];
FileStream fs = new FileStream("example.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
IAsyncResult result = fs.BeginRead(buffer, 0, buffer.Length, null, null);
// 模拟其他工作
Console.WriteLine("正在执行其他任务...");
int bytesRead = fs.EndRead(result);
fs.Close();
Console.WriteLine($"读取了 {bytesRead} 字节的数据。");
}
}
输出
正在执行其他任务...
读取了 100 字节的数据。
APM 模式在现代 C# 开发中已逐渐被淘汰,推荐使用 async/await
模式。
2. 基于事件的异步模式(EAP)
基于事件的异步模式(Event-based Asynchronous Pattern,EAP)通过事件来通知异步操作的完成。它通常与 BackgroundWorker
类一起使用。
示例代码
using System;
using System.ComponentModel;
class Program
{
static void Main()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += Worker_DoWork;
worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
worker.RunWorkerAsync();
Console.WriteLine("主线程继续执行其他任务...");
}
private static void Worker_DoWork(object sender, DoWorkEventArgs e)
{
// 模拟耗时操作
System.Threading.Thread.Sleep(2000);
e.Result = "任务完成";
}
private static void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine(e.Result);
}
}
输出
主线程继续执行其他任务...
任务完成
EAP 模式适合需要与 UI 交互的场景,因为它可以避免阻塞主线程。
3. 任务并行库(TPL)
任务并行库(Task Parallel Library,TPL)是 .NET 提供的一个强大的并发编程框架。它基于 Task
和 Task<TResult>
类,简化了多线程编程。
示例代码
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
Task<int> task = Task.Run(() => CalculateSum(100));
Console.WriteLine("正在执行其他任务...");
int result = await task;
Console.WriteLine($"计算结果: {result}");
}
static int CalculateSum(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
}
输出
正在执行其他任务...
计算结果: 5050
TPL 适合 CPU 密集型任务,但需要注意线程池的资源管理。
4. 异步/等待模式(async/await)
async/await
是 C# 中最常用的并发模式。它通过 async
和 await
关键字简化了异步编程。
示例代码
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
Console.WriteLine("开始下载...");
string content = await DownloadContentAsync("https://example.com");
Console.WriteLine($"下载完成,内容长度: {content.Length}");
}
static async Task<string> DownloadContentAsync(string url)
{
using HttpClient client = new HttpClient();
return await client.GetStringAsync(url);
}
}
输出
开始下载...
下载完成,内容长度: 1256
async/await
适合 I/O 密集型任务,但需要避免阻塞调用。
实际案例:并发下载器
以下是一个使用 async/await
实现并发下载器的示例:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
List<string> urls = new List<string>
{
"https://example.com",
"https://example.org",
"https://example.net"
};
List<Task<string>> downloadTasks = new List<Task<string>>();
foreach (var url in urls)
{
downloadTasks.Add(DownloadContentAsync(url));
}
string[] contents = await Task.WhenAll(downloadTasks);
Console.WriteLine("所有下载任务完成!");
}
static async Task<string> DownloadContentAsync(string url)
{
using HttpClient client = new HttpClient();
return await client.GetStringAsync(url);
}
}
总结
C# 提供了多种并发模式,每种模式都有其适用的场景。以下是选择并发模式的建议:
- APM:已过时,不推荐使用。
- EAP:适合与 UI 交互的场景。
- TPL:适合 CPU 密集型任务。
- async/await:适合 I/O 密集型任务。
通过合理选择并发模式,可以显著提高应用程序的性能和响应能力。
附加资源
练习
- 使用
async/await
实现一个并发文件下载器。 - 尝试将 TPL 与
async/await
结合,实现一个并行计算器。 - 研究
BackgroundWorker
类,并实现一个简单的进度条功能。
祝你学习愉快!