C# 中 Task
1. Task,它代表了一个异步操作的执行和完成。可以用来封装一个异步操作,使其可以在不阻塞主线程的情况下执行,并在操作完成后获取结果。
1 static void Main(string[] args) 2 { 3 MyFun(); 4 Console.Read(); 5 } 6 static void MyFun() 7 { 8 // var firstTask = new Task<int>(() => TaskMethod("First Task", 3)); 9 Task t1 = new Task<int>(()=>MyMethod("write")); 10 Task t2 = Task<int>.Factory.StartNew(() => MyMethod("red"));//这个会自动开始 11 t1.Start();//这个必须手动开始 12 } 13 static int MyMethod(string name) 14 { 15 Console.WriteLine($"I am {name}"); 16 return 0; 17 }
2. 示例:UseMethodAsync()通过Task.Run 将该操作提交给线程池,并使用 await 等待其完成获取到结果。
static async Task<int> LongOperationAsync() { // 模拟耗时操作 await Task.Delay(1000); return 42; // 假设这是耗时操作的返回结果 } static async Task UseMethodAsync() { int result = await Task.Run(() => LongOperationAsync()); Console.WriteLine($"操作结果: {result}"); }
3. 使用Task处理并行任务,并等待全部完成后获取结果(多个Task任务完成,新的任务才会完成)
static async Task ParallelProcessingAsync() { Task<int> task1 = Task.Run(() => LongOperationAsync()); Task<int> task2 = Task.Run(() => LongOperationAsync()); Task<int> task3 = Task.Run(() => LongOperationAsync()); // 等待所有任务完成 await Task.WhenAll(task1, task2, task3); // 可以继续处理任务结果 Console.WriteLine("所有任务已完成"); }
4. Task中的取消
static async Task<int> LongOperationWithCancellationAsync(CancellationToken cancellationToken) { await Task.Delay(1000, cancellationToken); return 42; } static async Task MyMethodWithCancellationAsync() { using (var cts = new CancellationTokenSource()) { Task<int> task = Task.Run(() => LongOperationWithCancellationAsync(cts.Token)); // 模拟超时逻辑,实际使用时可能基于其他条件 cts.CancelAfter(1000); // 1000毫秒(1秒)后取消任务 try { int result = await task; Console.WriteLine($"操作结果: {result}"); } catch (OperationCanceledException) { Console.WriteLine("操作已被取消"); } } }
5. Task中的错误处理
static async Task<int> OperationWithFailAsync() { // 模拟可能失败的操作 await Task.Delay(100); throw new InvalidOperationException("操作失败"); } static async Task HandleTaskAsync() { try { await Task.Run(() => OperationWithFailAsync()); } catch (Exception ex) { Console.WriteLine($"发生错误: {ex.Message}"); } }
6. Task中的继续处理Task.ContinueWith:可以指定在任务完成之后,应开始运行之后另一个特定任务
a. ContinueWith()会等待,直到firstTask运行状态达到 IsCompleted,因为TaskContinuationOptions中用的是OnlyOnRanToCompletion
1 static int TaskMethod(string name, int seconds) 2 { 3 Console.WriteLine("Task {0} is running.thread id {1},Is thread pool:{2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 4 Thread.Sleep(TimeSpan.FromSeconds(seconds)); 5 return 60 * seconds; 6 } 7 static void Main(string[] args) 8 { 9 var firstTask = new Task<int>(() => TaskMethod("First Task", 3)); 10 firstTask.ContinueWith(t=>Console.WriteLine("First Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),TaskContinuationOptions.OnlyOnRanToCompletion); 11 firstTask.Start(); 12 13 //主线程工作 14 Console.WriteLine("Back Work:thread id {0},Is thread pool:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 15 Console.Read(); 16 }
注意:不会影响主线程。
b.
1 static int TaskMethod(string name, int seconds) 2 { 3 Console.WriteLine("Task {0} is running.thread id {1},Is thread pool:{2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 4 Thread.Sleep(TimeSpan.FromSeconds(seconds)); 5 return 60 * seconds; 6 } 7 static void Main(string[] args) 8 { 9 Console.WriteLine("Main thread id {0},Is thread pool:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); 10 11 var firstTask = new Task<int>(() => TaskMethod("First Task", 3)); 12 var secondTask = new Task<int>(() => TaskMethod("Second Task", 2)); 13 firstTask.ContinueWith(t=>Console.WriteLine("First Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),TaskContinuationOptions.OnlyOnRanToCompletion); 14 15 16 firstTask.Start(); 17 secondTask.Start(); 18 19 // Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。 20 secondTask.ContinueWith(t => Console.WriteLine("Second Task Result:{0}..thread id {1},Is thread pool:{2}", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread), TaskContinuationOptions.OnlyOnRanToCompletion|TaskContinuationOptions.ExecuteSynchronously ); 21 22 23 //主线程工作 24 Console.Read(); 25 }
注释调此句: //Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。
由于主线程很早就结束了,因此secondTask只能接受到OnlyOnRanToCompletion,因此还是运行在线程池中。
不注释调此句: Thread.Sleep(TimeSpan.FromSeconds(4));//等待firstTask,secondTask及后续操作完成。
这里主线程休眠了足足4秒钟,足以让firstTask和secondTask两个任务完成运行,而后,由于secondTask的后续除了接受OnlyOnRanToCompletion外,还接受ExecuteSynchronously。
因此,后续运行中,由于主线程还没有结束,因此 ExecuteSynchronously得到认可,故secondTask的后续是在主线程上运行,不是在线程池。
7. Task的Task.WhenAny,WhenAll
static async Task<string> DoMethod(int time,string name="wo") { Console.WriteLine($"{name} come in."); await Task.Delay(TimeSpan.FromMilliseconds(time)); return string.Format("{0} have done this work,time is {1}", name, time); } static async Task TimeOutMethod(int needTimeOut) { Console.WriteLine($"needTimeOut={needTimeOut}"); var t = new Stopwatch(); t.Start();// 开始计时 var timeOutTask = Task.Run(() => Task.Delay(150).ContinueWith(_ => "Task timeOutTask finished after 150 seconds")); ;//创建超时任务。 var doing = DoMethod(needTimeOut);//需要执行的任务。 var task = await Task.WhenAny(timeOutTask, doing);//两个任务,只要有一个完成,就返回 Console.WriteLine(task.Result); t.Stop(); Console.WriteLine("used time:" + t.Elapsed.TotalMilliseconds); } static void Main(string[] args) { TimeOutMethod(50); TimeOutMethod(500); Console.Read(); }
说明:
传50做参数的时候,DoMethod先完成,所以返回:wo have done this work,time is 50
传500做参数的时候,timeOutTask先完成,返回:Task timeOutTask finished after 150 seconds
/// <summary> /// 多任务一起执行,并获取结果,及处理 /// </summary> /// <returns></returns> static async Task Tasks() { var t = new Stopwatch(); t.Start();// 开始计时 var list = new List<string>(); var t1 = DoMethod(1000, "1000"); var t2 = DoMethod(1500, "1500"); var t3 = DoMethod(1200, "1200"); var tasks = new[] { t1, t2, t3 }; //收集返回值 var process = tasks.Select(async tt => { var result = await tt; list.Add(result); }); //等待所有任务完成,才有返回值 await Task.WhenAll(process); foreach(var i in list) { Console.WriteLine(i); } t.Stop(); Console.WriteLine("used time:" + t.Elapsed.TotalMilliseconds); } static void Main(string[] args) { Tasks(); Console.Read(); }
等到所有任务都完成(时间短的还是先完成)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)