异步编程是现代软件开发中不可或缺的一部分,尤其是在处理耗时操作时。C#作为一种功能强大的编程语言,提供了多种实现异步编程的方式。本文将介绍C#中常用的五种异步编程方式,并附上示例代码。
1. 使用async和await关键字
C# 5.0引入了async和await关键字,极大地简化了异步编程。使用async标记的方法可以在不阻塞主线程的情况下执行异步操作,而await关键字则用于等待一个Task完成。
using System;
using System.Threading.Tasks;
public class AsyncExample
{
public static async Task Main(string[] args)
{
Console.WriteLine("调用异步方法前");
string result = await GetDataAsync("https://example.com/data");
Console.WriteLine("调用异步方法后");
Console.WriteLine(result);
}
public static async Task<string> GetDataAsync(string url)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
}
}
2. 使用Task类
Task类是.NET Framework 4.0引入的,用于表示一个异步操作。Task.Run方法是一个常用的方式来启动一个后台任务。
using System;
using System.Threading.Tasks;
public class TaskExample
{
public static async Task Main(string[] args)
{
Console.WriteLine("主线程,线程ID: " + Thread.CurrentThread.ManagedThreadId);
Task task1 = new Task(() => TaskFunc1());
task1.Start();
var result = Task.Run<string>(() => { return TaskFunc2(); });
Console.WriteLine(result.Result);
}
private static void TaskFunc1()
{
Console.WriteLine("Task方式一开启的线程ID: " + Thread.CurrentThread.ManagedThreadId);
}
private static string TaskFunc2()
{
return "Task方式二开启的线程ID: " + Thread.CurrentThread.ManagedThreadId;
}
}
3. 基于委托的异步方法
在委托类型中定义BeginInvoke()和EndInvoke()两个方法,可以实现异步编程。
using System;
using System.Threading;
public class DelegateAsyncExample
{
public static void Main(string[] args)
{
Console.WriteLine("调用异步方法前");
string param = "参数";
PostAsync(param);
Console.WriteLine("调用异步方法后");
Console.ReadKey();
}
private delegate void AsyncFoo(string param);
private static void PostAsync(object param)
{
AsyncFoo caller = Myfunc;
caller.BeginInvoke(param.ToString(), FooCallBack, caller);
}
private static void FooCallBack(IAsyncResult ar)
{
var caller = (AsyncFoo)ar.AsyncState;
caller.EndInvoke(ar);
}
private static void Myfunc(string param)
{
Console.WriteLine("通过委托来实现异步编程的");
}
}
4. 基于IAsyncEnumerable的异步数据流
IAsyncEnumerable是.NET Core 2.0引入的,提供了一种异步枚举大量数据的方式。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class AsyncStreamExample
{
public static async Task Main(string[] args)
{
await foreach (var item in GetLargeDataAsync())
{
Console.WriteLine(item);
}
}
public static async IAsyncEnumerable<int> GetLargeDataAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000); // 模拟异步操作
yield return i;
}
}
}
5. 基于TPL Dataflow的异步数据流处理
TPL Dataflow(Task Parallel Library Dataflow)提供了多种块(如BufferBlock、TransformBlock<T, T>等),可以组合起来构建数据处理管道。
using System;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
public class DataflowExample
{
public static async Task Main(string[] args)
{
var buffer = new BufferBlock<int>();
var processor = new TransformBlock<int, string>(async x => await ProcessAsync(x));
buffer.LinkTo(processor);
buffer.Post(1);
buffer.Post(2);
buffer.Complete();
await processor.Completion;
}
private static async Task<string> ProcessAsync(int x)
{
await Task.Delay(1000); // 模拟异步操作
return "Processed: " + x;
}
}
结论
异步编程是现代软件开发中不可或缺的一部分,尤其是在处理耗时操作时。C#提供了多种实现异步编程的方式,包括使用async和await关键字、Task类、基于委托的异步方法、基于IAsyncEnumerable的异步数据流以及基于TPL Dataflow的异步数据流处理。每种方式都有其适用场景和优势,开发者可以根据项目的具体需求选择合适的方式。