C#Task的四种使用方式

这段代码展示了如何使用Task和TaskFactory创建并启动多线程任务,分别通过Task和Task.Run以及两种TaskFactory的方式输出任务开始时的线程ID,揭示了异步编程的基础概念。
{
    Task task1 = new Task(() => Console.WriteLine($"task1 Start;   Thread ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
    task1.Start();
}
{
    Task task2 = Task.Run(() => Console.WriteLine($"task2 Start;   Thread ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
}
{
    TaskFactory taskFactory1 = new TaskFactory();
    taskFactory1.StartNew(() => Console.WriteLine($"taskFactory1 Start;   Thread ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
}
{
    TaskFactory taskFactory2 = Task.Factory;
    taskFactory2.StartNew(() => Console.WriteLine($"taskFactory2 Start;   Thread ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
}

在这里插入图片描述

<think>嗯,用户想要了解C#Task使用方法。之前用户提供了两篇站内引用材料,虽然内容有些概括,但可以提取关键信息:引用1提到Task是并发编程工具,引用2则强调异步编程的实战需求和常见困惑。 用户的核心需求很明确——需要Task的实用指南。从引用2作者提到"战战兢兢"的使用心态来看,用户可能更关注如何避免常见陷阱。结合C#最新文档,应该优先覆盖以下维度: 首先是基础创建方式Task.Run()和直接实例化的区别很关键;异步方法中的Task类型转换容易被忽略;异常处理聚合异常的机制需要单独强调;取消操作CancellationTokenSource的完整生命周期演示很重要。 考虑到引用1提到"高效并发",性能注意事项必须包含:要提醒Task.Run()的线程池本质,避免过度并行化反而降低性能。状态监控部分特别加入TaskStatus枚举说明,因为调试时任务状态不明是常见痛点。 示例代码准备采用阶梯式设计:从同步任务开始,逐步过渡到异步方法封装、异常传播、取消协作。特别注意在错误处理示例中展示Exception.InnerException的访问方式——这是引用2作者提到的"不受控制"场景的解决方案之一。 最后设置的两个问题有针对性:第一个针对引用1的"高效实践"要求,第二个呼应引用2提出的"异步代码必要性"困惑。这样既解决当前问题,也为后续深入讨论留出空间。 </think>以下是C#Task的完整使用指南,结合最佳实践和常见场景: --- ### **Task基础用法** #### 1. **创建Task** ```csharp // 方式1:直接实例化 var task = new Task(() => Console.WriteLine("Task执行")); task.Start(); // 方式2:使用Task.Run(自动启动) Task.Run(() => { Console.WriteLine("后台线程执行"); }); ``` #### 2. **异步方法封装** ```csharp public static async Task<int> CalculateAsync() { await Task.Delay(1000); // 模拟耗时操作 return 42; } // 调用异步方法 var result = await CalculateAsync(); ``` --- ### **关键操作指南** #### 1. **等待任务完成** ```csharp Task task = Task.Run(DoWork); task.Wait(); // 阻塞当前线程 await task; // 非阻塞等待(需在async方法内) ``` #### 2. **任务链式处理** ```csharp Task.Run(Step1) .ContinueWith(t => Step2(t.Result)) // 接收上一步结果 .ContinueWith(t => Step3(t.Result), TaskContinuationOptions.OnlyOnRanToCompletion); ``` #### 3. **异常处理** ```csharp try { await Task.Run(() => { throw new InvalidOperationException(); }); } catch (AggregateException ae) // 捕获聚合异常 { foreach (var e in ae.InnerExceptions) Console.WriteLine(e.Message); } ``` #### 4. **取消任务** ```csharp var cts = new CancellationTokenSource(); var token = cts.Token; Task longRunningTask = Task.Run(() => { while (true) { token.ThrowIfCancellationRequested(); // 业务逻辑 } }, token); // 外部触发取消 cts.CancelAfter(3000); ``` --- ### **高级特性** #### 1. **任务组合** ```csharp // 等待所有任务 await Task.WhenAll(task1, task2); // 等待任意任务 Task winner = await Task.WhenAny(task1, task2); ``` #### 2. **返回值处理** ```csharp Task<int> getNumberTask = Task.Run(() => 100); int number = await getNumberTask; ``` #### 3. **配置任务行为** ```csharp Task.Run(() => { // 长时运行任务(避免线程池回收) }, TaskCreationOptions.LongRunning); ``` --- ### **最佳实践** 1. **避免`.Result`和`.Wait()`** 在异步上下文中优先使用`await`,防止死锁[^1] 2. **合理使用`ConfigureAwait(false)`** 非UI场景可提升性能: ```csharp await GetDataAsync().ConfigureAwait(false); ``` 3. **控制并发数量** 使用`SemaphoreSlim`限制并行度: ```csharp var semaphore = new SemaphoreSlim(5); await semaphore.WaitAsync(); try { /* 操作 */ } finally { semaphore.Release(); } ``` --- ### **常见误区** ```csharp // 错误:同步阻塞异步方法(可能导致死锁) int result = CalculateAsync().Result; // 正确:异步等待 int result = await CalculateAsync(); ``` > 提示:在ASP.NET Core中无需手动配置线程池,框架已优化异步处理[^2] --- **参考文献** [^1]: Task的阻塞调用易引发死锁,尤其在UI线程或同步上下文受限环境 [^2]: ASP.NET Core的请求管道天生支持异步,无需额外线程调配 --- ### 相关问题 1. 如何在ASP.NET Core中优化Task的调度性能? 2. `Task.Run()`与`Task.Factory.StartNew()`有何本质区别? 3. 为什么说异步编程不等于多线程编程?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值