当前位置:首页 > C# > 正文

C#异步编程入门指南(深入理解Begin/End模式与APM模型)

在C#早期版本中,异步编程主要通过异步编程模型(Asynchronous Programming Model, APM)来实现,也就是我们常说的Begin/End模式。虽然现在更推荐使用基于async/await的TAP(Task-based Asynchronous Pattern)模型,但理解APM对于阅读旧代码、维护遗留系统仍然非常重要。

C#异步编程入门指南(深入理解Begin/End模式与APM模型) C#异步编程  Begin/End模式 APM模型 异步方法调用 第1张

什么是APM(异步编程模型)?

APM是.NET Framework 1.0时代引入的异步编程方式。它的核心思想是:每个同步方法都配有一对异步方法——BeginXxxEndXxx

  • BeginXxx:启动异步操作,立即返回一个 IAsyncResult 对象,并可选地传入回调函数。
  • EndXxx:用于获取异步操作的结果,或等待操作完成。如果操作尚未完成,它会阻塞当前线程直到完成。

一个简单的APM示例

假设我们要异步读取文件内容。我们可以使用 FileStreamBeginReadEndRead 方法:

using System;using System.IO;using System.Threading;class Program{    static void Main()    {        string filePath = @"example.txt";        byte[] buffer = new byte[1024];        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))        {            // 启动异步读取            IAsyncResult result = fs.BeginRead(buffer, 0, buffer.Length, null, null);            // 可以在这里做其他事情            Console.WriteLine("正在异步读取文件...");            // 等待并获取结果            int bytesRead = fs.EndRead(result);            string content = System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead);            Console.WriteLine("读取内容:" + content);        }    }}  

使用回调函数处理异步完成

你也可以在 BeginXxx 中传入一个回调函数(AsyncCallback),这样当异步操作完成后,系统会自动调用该回调,而无需主动调用 EndXxx 阻塞等待。

static void ReadFileCallback(IAsyncResult ar){    FileStream fs = (FileStream)ar.AsyncState;    try    {        int bytesRead = fs.EndRead(ar);        byte[] buffer = new byte[bytesRead];        Array.Copy(ar.AsyncState as byte[], buffer, bytesRead);        string content = System.Text.Encoding.UTF8.GetString(buffer);        Console.WriteLine("异步读取完成:" + content);    }    finally    {        fs.Close();    }}static void Main(){    string filePath = @"example.txt";    byte[] buffer = new byte[1024];    FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);    // 传入回调和状态对象    fs.BeginRead(buffer, 0, buffer.Length, ReadFileCallback, fs);    Console.WriteLine("主线程继续执行...");    Thread.Sleep(2000); // 模拟其他工作}  

APM的关键组件

要掌握C#异步编程中的APM,你需要理解以下核心概念:

  • IAsyncResult:表示异步操作的状态,包含 IsCompletedAsyncWaitHandle 等属性。
  • AsyncCallback:一个委托类型,用于定义异步完成时的回调方法。
  • AsyncState:在 BeginXxx 中传入的任意对象,可在回调中通过 ar.AsyncState 获取。

APM的优缺点

优点

  • 适用于所有 .NET Framework 版本。
  • 不阻塞调用线程(配合回调使用时)。

缺点

  • 代码复杂,容易出错。
  • 异常处理困难(异常在 EndXxx 中抛出)。
  • 难以组合多个异步操作。

现代替代方案:TAP(Task-based Asynchronous Pattern)

从 .NET Framework 4.5 开始,微软推荐使用基于 Taskasync/await 的TAP模型。它语法简洁、易于理解和维护。例如,上面的文件读取可以简化为:

static async Task ReadFileAsync(string path){    byte[] buffer = new byte[1024];    using (FileStream fs = File.OpenRead(path))    {        int bytesRead = await fs.ReadAsync(buffer, 0, buffer.Length);        string content = Encoding.UTF8.GetString(buffer, 0, bytesRead);        Console.WriteLine(content);    }}  

总结

虽然Begin/End模式在现代C#开发中已逐渐被TAP取代,但理解APM模型仍然是每个C#开发者的重要基础。它帮助我们理解异步操作的本质,并能更好地维护老项目。如果你刚开始学习异步方法调用,建议先掌握APM原理,再过渡到更现代的async/await

希望这篇关于C#异步编程的教程能帮助你轻松入门APM!