C#异步编程完全指南:async/await背后的状态机原理

news2026/3/27 1:36:21
# C#异步编程完全指南async/await背后的状态机原理## 引言在现代软件开发中异步编程已成为构建高响应、高吞吐量应用程序的基石。C# 作为一门不断演进的现代编程语言从 .NET Framework 4.5 开始引入了 async 和 await 关键字彻底改变了异步代码的编写方式。它们让开发者能够以同步代码的直观结构编写异步逻辑极大地提高了生产力。然而在简洁语法的背后隐藏着一个精巧而复杂的编译器魔法——**状态机State Machine**。本文将深入剖析 async/await 的底层实现从编译器如何将异步方法重写为状态机类到 Task 与 Awaiter 的协作机制再到性能考量与高级用法。通过大量代码示例和底层原理解析我们将揭开异步编程的神秘面纱帮助您写出更高效、更可靠的异步代码。---## 第一部分异步编程的演进### 1.1 同步编程的困境在早期的 .NET 开发中执行耗时操作如 I/O、网络请求时若采用同步方式线程会一直阻塞直到操作完成。这不仅浪费了宝贵的线程资源还导致用户界面卡死、服务器吞吐量下降。例如csharppublic string DownloadString(string url){using (var client new WebClient()){return client.DownloadString(url); // 同步阻塞}}当调用此方法时当前线程会挂起无法处理任何其他任务。### 1.2 异步编程的早期模式为了缓解阻塞问题开发者曾使用多种异步模式- **APMAsynchronous Programming Model**使用 BeginXxx 和 EndXxx 方法配合回调。代码分散且易出错。- **EAPEvent-based Asynchronous Pattern**通过事件和委托如 BackgroundWorker。仍难以管理复杂流程。- **基于任务的异步模式TAP**以 Task 和 TaskT 为核心结合 lambda 和 ContinueWith虽然比前两者优雅但当涉及多个异步操作时回调嵌套“回调地狱”依然存在。csharpclient.DownloadStringTaskAsync(url).ContinueWith(t {string result t.Result;// 处理结果继续嵌套...});### 1.3 async/await 的诞生C# 5.0 正式引入 async 和 await让异步代码能够以近乎同步的方式书写csharppublic async Taskstring DownloadStringAsync(string url){using (var client new HttpClient()){return await client.GetStringAsync(url);}}编译器将上述方法转化为一个状态机将 await 点分割成多个步骤使得线程在等待期间可以被释放回线程池从而极大提升资源利用率。---## 第二部分async/await 语法速览### 2.1 基本用法- 用 async 修饰方法表示它包含异步操作且可以包含 await 表达式。- 返回类型通常为 Task、TaskT 或 ValueTask。- await 表达式挂起方法直到等待的任务完成并返回结果如果有。csharppublic async Taskint ComputeAsync(){var data await FetchDataAsync(); // 挂起var result await ProcessDataAsync(data); // 再次挂起return result;}### 2.2 重要特性- **无阻塞等待**当 await 一个未完成的任务时控制权返回给调用者当前线程不会阻塞。- **异常传播**在异步方法内抛出的异常会被封装到返回的 Task 中调用者可通过 await 或 task.Result 捕获。- **上下文捕获与恢复**默认情况下await 会捕获当前 SynchronizationContextUI 线程或请求上下文并在恢复时继续在该上下文执行。---## 第三部分编译器魔法 —— 状态机揭秘为了理解异步方法的工作原理我们需要探究编译器生成的代码。使用 **ILSpy**、**dnSpy** 或 **SharpLab** 等工具可以查看反编译后的 C# 代码。下面我们逐步剖析。### 3.1 一个简单的异步方法假设我们有如下方法csharppublic async Taskint ExampleAsync(){Console.WriteLine(Start);int a 1;int b await GetNumberAsync();int c await GetAnotherNumberAsync(b);Console.WriteLine($Result: {c});return c;}### 3.2 状态机类的结构编译器会将 ExampleAsync 重写为一个生成的状态机类名称为 ExampleAsyncd__0其中数字随方法递增并实现 IAsyncStateMachine 接口。该类包含以下关键成员- **状态字段state**指示当前执行到哪个 await 点。初始值为 -1执行完成后为 -2 或其他终态。- **构建器builder**类型为 AsyncTaskMethodBuilderint负责管理 Task 的创建、完成和异常传播。- **提升的局部变量a、b、c**原来方法中的局部变量被提升为状态机的字段以便在多个步骤中保持值。- **参数如果有**方法的参数也会提升为字段。- **MoveNext() 方法**核心执行逻辑每次进入无论是初始调用还是 await 完成后的回调都会执行此方法根据 state 跳转到相应的代码段。简化后的状态机类大致如下csharp[CompilerGenerated]private sealed class ExampleAsyncd__0 : IAsyncStateMachine{public int 1__state; // 状态public AsyncTaskMethodBuilderint t__builder; // 构建器private int a; // 局部变量提升private int b;private int c;private int s__1; // 临时变量private TaskAwaiterint u__1; // 等待器private void MoveNext(){int num 1__state;int result;try{TaskAwaiterint awaiter;if (num ! 0 num ! 1){// 初始状态执行 await 之前的代码Console.WriteLine(Start);a 1;// 调用 GetNumberAsync 并获取等待器awaiter GetNumberAsync().GetAwaiter();if (!awaiter.IsCompleted){// 异步等待保存状态并注册回调num (1__state 0);u__1 awaiter;t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);return;}}else{// 从之前的等待恢复取出等待器awaiter u__1;}// 获取结果并继续if (num ! 1){b awaiter.GetResult(); // 获取第一个 await 的结果// 调用 GetAnotherNumberAsyncawaiter GetAnotherNumberAsync(b).GetAwaiter();if (!awaiter.IsCompleted){// 再次异步等待1__state 1;u__1 awaiter;t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);return;}}else{awaiter u__1;}c awaiter.GetResult(); // 获取第二个 await 的结果Console.WriteLine($Result: {c});result c;}catch (Exception exception){// 异常时通知构建器并设置状态为 -21__state -2;t__builder.SetException(exception);return;}// 正常完成1__state -2;t__builder.SetResult(result);}[DebuggerHidden]private void SetStateMachine(IAsyncStateMachine stateMachine){// 默认实现主要用于调试器支持}}同时原始异步方法被替换为csharppublic Taskint ExampleAsync(){ExampleAsyncd__0 stateMachine new ExampleAsyncd__0();stateMachine.t__builder AsyncTaskMethodBuilderint.Create();stateMachine.1__state -1;stateMachine.t__builder.Start(ref stateMachine);return stateMachine.t__builder.Task;}### 3.3 MoveNext 的执行流- **首次调用**Start 方法会调用 MoveNext。此时 state 为 -1进入初始代码段执行第一个 await 之前的代码然后获取 awaiter如果任务已经同步完成IsCompleted true则直接继续执行否则保存状态、等待器并注册回调通过 AwaitUnsafeOnCompleted然后返回当前线程不阻塞。- **当等待的任务完成时**AwaitUnsafeOnCompleted 会将 MoveNext 注册为任务的延续continuation。任务完成后会触发 MoveNext 再次执行此时 state 被设置为 0 或 1因此进入对应的恢复分支从之前保存的等待器中获取结果然后继续后续逻辑。- **状态切换**每次遇到 await 且任务未完成时状态机会将状态字段设为新的值并注册回调。当所有代码执行完毕或发生异常时状态机最终调用 builder.SetResult 或 SetException 来完成返回的 Task。### 3.4 为什么需要提升局部变量在原始的同步方法中局部变量如 a, b, c是存储在栈上的。但由于异步方法可能在多个线程上恢复执行例如在不同线程池线程上继续栈帧早已不复存在。因此编译器必须将这些变量提升为状态机的字段使它们能够在等待期间持久化。同样参数也被提升为字段。---## 第四部分Task 与 Awaiter 模式### 4.1 Task 与 TaskTTask 代表一个异步操作它可以处于 Created、WaitingForActivation、RanToCompletion、Faulted 或 Canceled 等状态。TaskT 继承自 Task额外包含一个 Result 属性。Task 提供了 ContinueWith 等方法用于组合但 await 提供了更简洁的语法。### 4.2 等待器模式Awaiter Pattern任何可以被 await 的类型必须满足以下条件- 具有可访问的 GetAwaiter() 实例方法或扩展方法。- 返回的类型awaiter必须实现 INotifyCompletion 接口或包含 IsCompleted、GetResult() 和 OnCompleted 方法。Task 和 TaskT 的 GetAwaiter 返回 TaskAwaiter 或 ConfiguredTaskAwaitable。其核心成员csharppublic struct TaskAwaiterTResult : ICriticalNotifyCompletion{public bool IsCompleted { get; }public TResult GetResult();public void OnCompleted(Action continuation);public void UnsafeOnCompleted(Action continuation);}- **IsCompleted**若任务已完成包括成功、失败或取消返回 true表示 await 可以同步获取结果无需挂起。- **GetResult()**返回任务的结果若任务出错则抛出异常。- **OnCompleted / UnsafeOnCompleted**用于注册延续回调即 MoveNext。当任务完成时回调被调度执行。对于 TaskGetResult() 返回 void但同样会抛出异常。### 4.3 ConfigureAwait 的作用默认情况下await 会捕获当前 SynchronizationContext 或 TaskScheduler并在恢复时尝试在此上下文中执行 MoveNext。这在 UI 应用中至关重要如 WPF 或 WinForms因为 UI 元素只能在创建它们的线程上访问。但在类库或高吞吐量服务中往往不需要恢复上下文通过 ConfigureAwait(false) 可以跳过捕获提高性能并避免死锁。csharpawait httpClient.GetStringAsync(url).ConfigureAwait(false);此方法返回 ConfiguredTaskAwaitable其等待器不会捕获上下文而是在任意可用线程上恢复。---## 第五部分深入 AsyncTaskMethodBuilder### 5.1 构建器的职责AsyncTaskMethodBuilderT 是状态机与 Task 之间的桥梁。它负责- 创建 TaskT 对象。- 提供 Start 方法启动状态机。- 提供 AwaitUnsafeOnCompleted 方法将 MoveNext 注册为延续。- 通过 SetResult 和 SetException 最终完成 Task。对于 Task非泛型使用 AsyncTaskMethodBuilder。### 5.2 Start 方法Start 方法通常由编译器在异步方法的入口调用csharpstateMachine.t__builder.Start(ref stateMachine);Start 的内部逻辑大致如下简化- 调用 MoveNext 开始执行。- 如果 MoveNext 抛出了异常且未在内部捕获则捕获并设置异常。### 5.3 AwaitUnsafeOnCompleted 的魔法在状态机中当遇到 await 且 awaiter.IsCompleted 为 false 时会调用csharpt__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);这个方法做了以下几件事1. 将当前状态机this包装为一个 Action 委托MoveNext 的调用。2. 调用 awaiter.UnsafeOnCompleted(action)将 action 注册为任务的延续。3. 在注册过程中如果 awaiter 实现了 ICriticalNotifyCompletion会使用 UnsafeOnCompleted性能更优否则使用 OnCompleted。4. 当任务完成时延续会被调度最终调用 MoveNext继续执行。值得一提的是整个过程中没有额外的线程阻塞所有操作都是基于回调的。---## 第六部分执行上下文流与同步上下文### 6.1 执行上下文ExecutionContext在异步操作中某些上下文信息如安全上下文、线程静态变量、AsyncLocalT 等需要在异步流中流动。ExecutionContext 负责捕获和还原这些数据。当 await 注册延续时AsyncTaskMethodBuilder 会捕获当前的 ExecutionContext如果配置为捕获以便在延续执行时恢复。默认情况下async 方法会自动流动 ExecutionContext因此 AsyncLocalT 等能够跨 await 保留。### 6.2 同步上下文SynchronizationContext同步上下文定义了如何在特定线程上执行委托如 UI 线程。await 默认会捕获当前的 SynchronizationContext除非使用 ConfigureAwait(false)并在延续时通过 context.Post 或 Send 执行回调。这对于保持 UI 线程亲和性至关重要。在 ASP.NET经典中SynchronizationContext 用于将请求上下文如 HttpContext.Current关联到异步延续但 ASP.NET Core 不再设置自定义同步上下文因此默认 ConfigureAwait(false) 的影响较小。---## 第七部分异常处理与取消### 7.1 异常的传播在异步方法中异常的处理遵循以下规则- 如果异常发生在 await 之前并且没有被捕获则它会被抛出到调用方但通过返回的 Task 包装。- 如果异常发生在 await 内部即被等待的任务抛出异常则在 awaiter.GetResult() 时重新抛出并被状态机的 catch 块捕获通过 builder.SetException 设置到返回的 Task 中。- 如果 async void 方法不推荐抛出异常则会直接引发到当前同步上下文可能导致进程崩溃。### 7.2 取消支持异步操作通常通过 CancellationToken 实现取消。在异步方法内部可以在循环中检查 token.IsCancellationRequested或将 token 传递给支持取消的异步方法。当任务被取消时TaskCanceledException 或 OperationCanceledException 会通过 await 传播。状态机对于取消的处理与普通异常相同最终通过 SetException 将异常包装到返回的任务中。---## 第八部分性能考量与最佳实践### 8.1 避免 async void除了事件处理程序外应始终返回 Task 或 TaskT。async void 方法难以追踪完成状态和异常且异常会直接抛到同步上下文容易导致应用程序崩溃。### 8.2 尽量使用 ConfigureAwait(false)在库代码中默认使用 ConfigureAwait(false) 可以避免不必要的上下文捕获和切换提升性能并防止死锁。但要注意在需要恢复上下文的代码如 UI 事件处理中不应使用。### 8.3 避免同步阻塞永远不要用 task.Result 或 task.Wait() 在同步上下文中等待异步任务这可能导致死锁尤其是在 UI 或 ASP.NET 经典上下文中。始终使用 await。### 8.4 使用 ValueTask 优化当异步操作频繁同步完成时使用 ValueTaskT 可以减少内存分配。例如缓存结果时同步路径返回 new ValueTaskT(result)异步路径返回 new ValueTaskT(task)。ValueTask 是结构体避免堆分配但需小心使用只能被消费一次。### 8.5 考虑性能分析状态机本身有一定开销每个异步方法生成一个类字段和 MoveNext 逻辑。对于热路径应避免不必要的 async/await可以考虑直接返回 Task 或使用 ValueTask。### 8.6 内存泄漏风险如果异步方法持有对大对象的引用通过提升的局部变量并且长时间未完成例如无限循环或未取消的任务这些对象可能无法被回收导致内存泄漏。确保及时取消或完成异步任务。---## 第九部分高级主题### 9.1 自定义等待器我们可以为自定义类型实现等待器模式使其能够被 await。例如实现一个简单的 WaitableTimercsharppublic class WaitableTimer{private readonly TaskCompletionSourcebool _tcs new();private readonly Timer _timer;public WaitableTimer(TimeSpan delay){_timer new Timer(_ _tcs.SetResult(true), null, delay, Timeout.InfiniteTimeSpan);}public TaskAwaiterbool GetAwaiter() _tcs.Task.GetAwaiter();}使用csharpawait new WaitableTimer(TimeSpan.FromSeconds(2));注意需要实现 GetAwaiter 返回一个符合等待器模式的对象。通常我们直接返回 TaskAwaiter 或实现自定义结构。### 9.2 异步流IAsyncEnumerableC# 8.0 引入了异步流通过 await foreach 消费异步生成的数据。编译器为异步迭代器生成的状态机更为复杂因为它需要处理 MoveNextAsync 和 IAsyncDisposable。原理类似但状态机实现 IAsyncStateMachine 和 IAsyncEnumerableT。### 9.3 异步同步锁使用 SemaphoreSlim 的 WaitAsync 可以实现异步锁避免阻塞线程csharpprivate readonly SemaphoreSlim _semaphore new(1, 1);public async Task AccessResourceAsync(){await _semaphore.WaitAsync();try{// 访问共享资源}finally{_semaphore.Release();}}状态机在此处同样发挥作用。### 9.4 AsyncLocalT 与逻辑调用上下文AsyncLocalT 允许在异步流中传递数据其底层依赖于 ExecutionContext 的流动。这对于日志记录、事务传播等场景非常有用。### 9.5 低级别控制UnsafeOnCompleted 与 ValueTask在构建高性能库时有时需要直接操作等待器和延续。但大多数情况下依赖编译器生成的状态机已足够。---## 第十部分调试与诊断### 10.1 调试异步方法在 Visual Studio 中异步方法的调试体验较好。可以在 await 处设置断点查看调用堆栈和局部变量。但需要注意由于状态机将局部变量提升为字段调试器需要能够正确显示它们。### 10.2 异步栈跟踪在 .NET Core 中异步异常堆栈经过优化通常会保留原始调用链但有时可能被截断。使用 Exception.StackTrace 可以看到部分信息或通过 Task.Exception 获取内部异常。### 10.3 使用诊断工具- **dotnet-trace** 和 **PerfView** 可以分析异步方法的性能和 GC 分配。- **Concurrency Visualizer**Visual Studio帮助识别异步任务中的线程活动。---## 结语async/await 是 C# 中优雅而强大的特性其背后的状态机机制展现了编译器设计的精妙。理解状态机的工作原理不仅有助于编写高性能的异步代码还能帮助我们诊断死锁、性能瓶颈等疑难问题。从早期的异步模式到现代基于状态机的实现C# 异步编程经历了深刻的演进。掌握这些底层知识将使你在构建高响应、高扩展性的应用时更加得心应手。---## 参考文献与进一步阅读- Microsoft Docs: [Async in depth](https://learn.microsoft.com/en-us/dotnet/standard/async-in-depth)- Stephen Toub: [The managed threading and async blog](https://devblogs.microsoft.com/pfxteam/)- Jon Skeet: [C# in Depth, Fourth Edition](https://www.manning.com/books/c-sharp-in-depth-fourth-edition)- [SharpLab](https://sharplab.io/) – 在线查看编译器生成代码- [.NET Source Reference](https://source.dot.net/) – AsyncTaskMethodBuilder 等源码---*本文旨在提供一个全面且深入的视角帮助开发者理解 C# 异步编程的内部运作。通过将理论与实践结合相信你已对状态机有了深刻的认识。*

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2452838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…