C#异步Task
异步:多任务开始执行,只需要主任务 A 执行完成就算结束,主任务执行的时候,可以同时执行异步任务 B、C,主任务 A 可以不需要等待异步任务 B、C 的结果。
在C#中,异步编程主要通过async和await关键字来实现。这两个关键字是编写异步代码的核心,可以让你用同步的方式来写异步的代码。
internal class Program
{
static async void Main(string[] args)
{
Console.WriteLine("异步操作开始");
Console.WriteLine(await AsyncExample.DelayAsync()); // 启动异步并等待任务完成
Console.WriteLine("异步结束");
}
}
public class AsyncExample
{
public static async Task<string> DelayAsync()
{
// 模拟一个长时间运行的任务,如调用一个API或数据库
await Task.Delay(1000); // 延迟1秒(1000毫秒)
return "完成操作";
}
}
Task使用详情
在C#中,Task 是用于表示异步操作的类。它属于 System.Threading.Tasks 命名空间,并允许你以异步方式执行代码,从而不阻塞主线程。这对于I/O密集型操作(如网络请求或文件读写)或CPU密集型任务非常有用,因为它们可以让应用程序在等待操作时继续处理其他任务。
Task简单的使用
使用Task.Run()方法可以将工作提交给线程池来异步执行
Task<int> task = Task.Run(() =>
{
int result = LongRunningCalculation(); // 长时间运行的计算
return result;
});
// 等待任务完成并获取结果
int finalResult = await task;
创建task对象,使用start启动异步
除了Task.Run(),还可以直接实例化Task并通过.Start()方法手动启动
Console.WriteLine("开始异步任务...");
Task task1 = new Task(() =>
{
Console.WriteLine($"开始工作...");
System.Threading.Thread.Sleep(1000); // 模拟耗时工作
Console.WriteLine($"工作完成!");
});
task1.Start(); // 启动异步
Console.WriteLine("所有任务都已完成!");
使用 Task.WhenAll 等待多个任务完成
static async void Main(string[] args)
{
Console.WriteLine("开始多个异步任务...");
Task task1 = Task.Run(() => DoWork("任务1"));
Task task2 = Task.Run(() => DoWork("任务2"));
Task task3 = Task.Run(() => DoWork("任务3"));
// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("所有任务都已完成!");
}
static void DoWork(string taskName)
{
Console.WriteLine($"{taskName} 开始工作...");
System.Threading.Thread.Sleep(1000); // 模拟耗时工作
Console.WriteLine($"{taskName} 工作完成!");
}
使用工厂模式创建任务
// 使用 Task.Factory 创建一个任务
Task task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Hello from the task!");
});
// 等待任务完成
task.Wait();
异步和多线程的区别和使用场景
区别
C#中的异步编程(Asynchronous Programming)和多线程(Multithreading)都用于编写能同时处理多个任务的程序,但它们有重要的区别:
异步编程主要用于I/O密集型任务,而多线程可以用于CPU密集型任务。
异步方法在不阻塞调用线程的情况下等待长时间运行的任务完成。
多线程可以在多个线程之间分配CPU时间,从而允许它们在同一时间内执行。
异步通常比多线程更高效,因为它减少了线程间的上下文切换成本。
场景
当需要执行I/O操作时,使用异步操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。