C#中System.Threading.Tasks库的使用

 更新时间:2025年06月29日 08:36:35   作者:CoderIsArt  
System.Threading.Tasks是.NET的TAP核心,提供异步编程模型,本文主要介绍了C#中System.Threading.Tasks库的使用,具有一定的参考价值,感兴趣的可以了解一下

System.Threading.Tasks 是 .NET 中任务并行库(Task Parallel Library, TPL)的核心组件,它提供了基于任务的异步编程模型,是现代 .NET 并发编程的基础。

设计原理

1. 核心目标

  • 抽象并发工作:将并发操作抽象为"任务"概念

  • 资源高效利用:自动管理线程池资源

  • 组合性:支持任务链式操作和组合

  • 取消支持:内置取消操作机制

  • 状态跟踪:提供任务生命周期管理

2. 关键组件

  • Task/Task<T>:表示异步操作的核心类

  • TaskScheduler:控制任务如何、何时被执行

  • TaskFactory:提供创建和启动任务的便捷方法

  • CancellationToken:任务取消机制

  • TaskCompletionSource:手动控制任务生命周期

3. 架构层次

  • 用户层:开发者直接使用的Task API

  • 调度层:TaskScheduler管理任务执行

  • 线程池层:实际执行工作的底层线程池

典型用法示例

示例1:基础异步任务

// 创建并运行简单任务
Task.Run(() => 
{
    Console.WriteLine("任务在后台线程执行");
    Thread.Sleep(1000); // 模拟工作
    Console.WriteLine("任务完成");
});

// 带返回值的任务
Task<int> calculateTask = Task.Run(() => 
{
    Thread.Sleep(500);
    return 42; // 计算结果
});

// 等待任务完成并获取结果
int result = await calculateTask;
Console.WriteLine($"计算结果: {result}");

应用场景:CPU密集型后台计算,不阻塞UI线程。

示例2:任务组合与延续

// 创建三个任务
Task<string> task1 = Task.Run(() => "Hello");
Task<string> task2 = Task.Run(() => "World");
Task<int> task3 = Task.Run(() => 2023);

// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);

// 使用结果组合输出
Console.WriteLine($"{task1.Result} {task2.Result} {task3.Result}");

// 任务延续
Task continuation = task1.ContinueWith(t => 
{
    Console.WriteLine($"前一个任务的结果: {t.Result}");
}, TaskContinuationOptions.OnlyOnRanToCompletion);

应用场景:并行执行多个独立操作,然后合并结果或执行后续操作。

示例3:高级任务控制

// 使用TaskCompletionSource手动控制任务
var tcs = new TaskCompletionSource<string>();

// 模拟异步回调
Timer timer = new Timer(_ => 
{
    try
    {
        // 模拟工作
        string result = DateTime.Now.ToString();
        tcs.SetResult(result); // 手动完成任务
    }
    catch (Exception ex)
    {
        tcs.SetException(ex); // 手动设置异常
    }
}, null, 1000, Timeout.Infinite);

// 等待任务完成
try
{
    string timeString = await tcs.Task;
    Console.WriteLine($"当前时间: {timeString}");
}
catch (Exception ex)
{
    Console.WriteLine($"任务失败: {ex.Message}");
}

应用场景:将基于回调的异步API转换为基于任务的异步模式(TAP)。

示例4:取消任务

var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

// 创建可取消的任务
Task longRunningTask = Task.Run(() => 
{
    for (int i = 0; i < 100; i++)
    {
        token.ThrowIfCancellationRequested(); // 检查取消请求
        Thread.Sleep(100); // 模拟工作
        Console.WriteLine($"进度: {i}%");
    }
}, token);

// 3秒后取消任务
cts.CancelAfter(3000);

try
{
    await longRunningTask;
}
catch (OperationCanceledException)
{
    Console.WriteLine("任务被取消");
}

应用场景:长时间运行的操作需要提供取消功能。

核心概念深入

1. 任务状态机

任务有以下几种状态:

  • Created:已创建但未调度

  • WaitingForActivation:等待激活

  • WaitingToRun:已调度但未开始执行

  • Running:正在执行

  • WaitingForChildrenToComplete:等待子任务完成

  • RanToCompletion:成功完成

  • Canceled:被取消

  • Faulted:因异常失败

2. 任务调度策略

  • 线程池调度器:默认调度器,使用线程池线程

  • 同步上下文调度器:在特定同步上下文(如UI线程)执行

  • 自定义调度器:可继承TaskScheduler实现特殊调度逻辑

3. 异常处理

任务中的异常会被捕获并存储在 Task.Exception 属性中,当等待任务或访问Result属性时,这些异常会被重新抛出。

Task faultyTask = Task.Run(() => throw new InvalidOperationException("出错了"));

try
{
    await faultyTask;
}
catch (InvalidOperationException ex)
{
    Console.WriteLine($"捕获到异常: {ex.Message}");
}

最佳实践

  • 避免Task.Wait和Task.Result:可能导致死锁,优先使用await

  • 合理使用ConfigureAwait:库代码应使用ConfigureAwait(false)

  • 注意任务生命周期:长时间运行的任务应考虑取消支持

  • 避免过度并行化:太多并行任务会导致线程池饥饿

  • 正确处理异常:确保所有任务异常都被处理

性能考虑

  • 任务创建开销:轻量级但非零成本,高频场景考虑对象池

  • 线程池压力:大量短任务可能导致线程池频繁调整

  • 同步上下文:不必要地回到原始上下文会影响性能

System.Threading.Tasks 提供了强大而灵活的并发编程模型,是现代 .NET 应用程序中处理异步和并行操作的首选方式。

到此这篇关于C#中System.Threading.Tasks库的使用的文章就介绍到这了,更多相关C# System.Threading.Tasks内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#中StringBuilder类的使用总结

    C#中StringBuilder类的使用总结

    本篇文章主要是对C#中StringBuilder类的使用方法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • C# 监控 Windows 文件夹的方法

    C# 监控 Windows 文件夹的方法

    这篇文章主要介绍了C# 监控 Windows 文件夹的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • C#窗口实现单例模式的方法

    C#窗口实现单例模式的方法

    本文介绍了C#窗口实现单例模式的方法,对于一个软件如果第二次打开程序,就把已经启动的那个进程的窗口放到最前端显示,需要了解的朋友可以参考下
    2015-07-07
  • .net使用cap实现消息异步处理

    .net使用cap实现消息异步处理

    CAP 是一个基于 .NET Standard 的 C# 库,它是一种处理分布式事务的解决方案,同样具有 EventBus 的功能,它具有轻量级、易使用、高性能等特点,本文给大家介绍了.net下使用cap实现消息异步处理,需要的朋友可以参考下
    2024-05-05
  • C#获取Windows10屏幕缩放比例的操作方法

    C#获取Windows10屏幕缩放比例的操作方法

    这篇文章主要介绍了C#获取Windows10屏幕的缩放比例,接下来介绍如何获取Display resolution中显示的实际分辨率,本文通过示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2021-12-12
  • WPF实现炫酷的界面交互效果的代码详解

    WPF实现炫酷的界面交互效果的代码详解

    在当今竞争激烈的软件市场中,用户界面的交互体验至关重要,一个拥有炫酷动画特效的应用程序,不仅能吸引用户的注意力,还能显著提升用户与界面的交互流畅度和愉悦感,本文将深入剖析WPF动画特效的各个方面,通过大量详细的代码示例和对关键概念的深入解释
    2025-02-02
  • 解析使用C# lock同时访问共享数据

    解析使用C# lock同时访问共享数据

    本篇文章是对使用C# lock同时访问共享数据进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C#实现扫描局域网内的所有IP和端口

    C#实现扫描局域网内的所有IP和端口

    这篇文章主要为大家详细介绍了如何利用C#实现扫描局域网内的所有IP和端口的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 解析C#中@符号的几种使用方法详解

    解析C#中@符号的几种使用方法详解

    本篇文章是对C#中@符号的几种使用方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • WPF自定义实现雷达图控件的示例详解

    WPF自定义实现雷达图控件的示例详解

    雷达图用于表示不同内容的占比关系,在项目中有广泛的应用,但是目前未曾有封装良好的雷达图控件,所以本文分享了如何封装一个通用的雷达图控件,希望对大家有所帮助
    2023-08-08

最新评论