从订单改造到event Action<string>:C#委托与事件实战指南
从一次改造说起为什么回调会要了老命很多人在初学C#时对委托、event、Action 这几个概念总是处于“看着认识一用就混”的状态。我最早也是。当时团队里有一个老项目订单状态一旦变化需要同时通知短信服务、操作日志模块、数据统计模块甚至还要刷新一个后台管理界面。原始代码于是变成了这样在一个方法里依次调用 SmsService.Send()、Logger.Write()、StatService.Add()。第一版还好只通知三处。后面需求越来越多每加一个通知对象就要改一次核心业务方法而且这些服务类都是直接new出来的耦合度直线上升。最离谱的一次短信通道超时整个订单流程被拖慢了2秒。直到我带着团队重构把这块改成“事件驱动”才算彻底解脱。这篇文章不是教科书式的概念罗列而是围绕标题里的委托 event Action / event Action 做一次实战归纳。适合几类人看刚开始学C#、被委托事件绕晕的人写过一点代码但不敢在项目里用event的人准备面试、需要把“什么是委托和事件”讲清楚的人。看完全文你应该能直接写出一个带有 event Action 事件的发布器也能避开我当年踩过的坑。场景还原一处通知牵动多个模块先还原一下那个订单场景的代码结构public class OrderService { public void CompleteOrder(Order order) { // 核心业务改状态、落库 order.Status OrderStatus.Completed; _db.Save(order); // 通知各种模块 SmsService.Send(order.UserPhone, 您的订单已完成); Logger.Write($订单 {order.Id} 完成); StatService.AddCompleted(order.CreatedAt); } }每次有新模块要关心订单完成就得改 CompleteOrder 方法加一行调用。如果有一天短信服务挂了因为 Send() 是同步调用还会阻塞主流程。这就是高耦合带来的问题。最土的办法是定义一个接口把所有关心订单状态的观察者收集到一个列表里轮询调用。这能用但很重。其实C#早就给了更轻量的解决方案委托。所谓委托就是“把一个方法本身当作变量传来传去”。你不必让所有观察者实现同一个接口只需要把各自的方法塞给调用方时机到了再逐个触发。委托的本质方法也能当对象理解委托先要扭转一个思维定式方法不只是写在类里的一段代码它也可以是一个对象。就像你给外卖小哥留了一个电话号码小哥不会把电话本身带走只会把这个号码记下来。到了饭点他按号码打过去。委托就是这个“号码”它记录了“哪个对象上的哪个方法”别人需要调你的方法时不需要知道你姓甚名谁只需要持有一个委托实例。在C#里定义一个委托本质是定义一种“方法签名规范”public delegate void NotifyHandler(string message);这句声明代表所有符合“有一个string参数、无返回值”的方法都可以被赋值给 NotifyHandler 类型的变量。于是可以这样用NotifyHandler handler; handler Console.WriteLine; handler(订单已完成);Console.WriteLine 是一个接收 string 参数、无返回值的方法它和 NotifyHandler 的签名完全匹配。这种直接拿方法名赋值给委托类型的写法叫“方法组转换”从 C# 1.0 一直保留到今天。委托类型和实例的关系和类与对象非常像。委托类型好比一份岗位JD定义了这个职位需要哪些技能委托实例则是实际签下的员工背后绑定了具体的人和方法。别再造轮子了Action 与 Action 的日常用法C# 1.0 时代用委托就得写一大堆 delegate 声明。比如上面那个 NotifyHandler即使全项目里只有一处用也要单独声明一次。写多了很繁琐。后来.NET框架内置了一批通用委托类型其中最常用的就是 System.Action委托类型参数返回值Action无参数voidAction1个参数voidActionT1, T22个参数voidActionT1, T2, T33个参数void......void从声明到调用Action 是这样用的Actionstring log; log msg Console.WriteLine($[LOG] {msg}); log(hello world);lambda 表达式 这种写法在这里就是创建一个没有名字的委托实例相当于“顺手注册了一段匿名逻辑”。你会发现带委托的代码几乎都被 lambda 占满了这正是 Action 配合现代C#写法的自然状态。Action 与 Action 如何选简单判别方法事件或回调本身是否需要传递一条消息。只需要告诉外界“事情发生了”用 event Action。比如商品上下架、用户登录状态切换。需要把具体内容跟着事件一起发出去用 event Action 。比如日志消息、异常信息、某段文本通知。不要动不动就定义自己的 delegate 类型除非这个委托类型要在多处复用、且有明确的业务语义。否则直接用内置的 Action/Func代码读起来干净很多。顺带看懂 Func和 Action 肩并肩的还有 Func它是有返回值的委托。Func 代表“无参数、返回 string 的方法”Funcstring, int 代表“接收 string、返回 int 的方法”。通常用于需要拿到执行结果的地方比如查询数据、计算处理。因为本文集中在 void 回调场景主要都是 Action 的活儿。事件对 Action 泛型的应用很常见尤其是写网络通讯程序时收到消息、解析消息、上报状态用 event Action 一条链下来非常顺。这也是上位机、服务端开发里普遍存在的写法。event一种被加了“只读权限”的委托很多人面试时会说“事件就是委托的一种”。这句话没错但不严谨。更准确的说法是事件是一种基于委托的“受限引用”。它对外只暴露了订阅和退订-两个入口把替换、调用、清零的权利全部收归类自己。没加 event 的 public 委托字段有多危险先看反面教材public class Publisher { public Actionstring Notify; }这个字段是 public 的外部随便玩var p new Publisher(); p.Notify Console.WriteLine; // 合法整体替换 p.Notify msg Console.WriteLine(msg); // 合法追加 p.Notify(直接触发); // 合法任何人都能主动点火 p.Notify null; // 合法直接把监听列表清空看出问题了吗事件发布者原本应该掌握“何时触发”的决定权结果外界可以把整个通知管线复位甚至绕过内部逻辑直接触发。这在多模块协作项目里等于把钥匙发给了所有人。加了 event 之后编译器干了什么同样的字段加一个 event 试试public class Publisher { public event Actionstring Notify; }此时外部仍然可以 和 -但尝试触发或者赋值编译直接报错var p new Publisher(); p.Notify Console.WriteLine; // OK p.Notify(直接触发); // 编译错误事件只能出现在 或 - 左边 p.Notify Console.WriteLine; // 编译错误不能对事件直接赋值 p.Notify null; // 编译错误编译器为“event 字段”做的事等价于这样的代码private Actionstring _notify; public event Actionstring Notify { add { _notify value; } remove { _notify - value; } }也就是说event 的本质是一个私有委托字段 一对 add/remove 访问器。类外面的人只能通过 add/remove 调整监听列表根本碰不到那个真正的委托实例。这也是为什么我们常说“事件是安全的委托”。触发权在类内部订阅权在外部事件配合方法使用时正确的姿势是public class Publisher { public event Actionstring Notify; public void Run() { // 业务逻辑...... Notify?.Invoke(任务完成); } }只有在类内部才可以调用 Notify()因为只有自己知道业务到什么节点了、该不该通知。外面的人负责订阅类负责触发。各自守好自己的边界。这里有个容易忽略的细节调用事件前为什么要判空或使用 ?.Invoke因为事件可能一个订阅者都没有此时 Delegate 是 null直接 Invoke 会抛 NullReferenceException。Notify?.Invoke(...)的意思是“如果有订阅者才触发”是防御空引用的标准做法。自定义 add/remove 的进阶用法默认的 event 字段用法已经能满足日常需要。但有时你需要自己做点手脚比如加日志private Actionstring _notify; public event Actionstring Notify { add { Console.WriteLine(添加订阅者); _notify value; } remove { Console.WriteLine(移除订阅者); _notify - value; } }这个技巧在调试事件泄漏问题时特别好用能从 add/remove 的日查看谁订阅了、谁忘记退订了。不过注意一旦自定义 add/remove就是自己接管了委托字段的管理线程安全问题也变成了你的责任因此不确定没必要别乱加。实战用 event Action 搭一个多订阅者通知器把前面讲的东西拼起来看一个完整案例。需求很简单有一个消息中心任何模块都可以向它投稿所有订阅者都能收到同一条消息。最小实现发布器与订阅者public class MessageCenter { public event Actionstring MessagePublished; public void Publish(string message) { MessagePublished?.Invoke(message); } }订阅端可以同时挂好几个订阅者var center new MessageCenter(); center.MessagePublished msg Console.WriteLine($[控制台] {msg}); center.MessagePublished msg File.AppendAllText(app.log, msg Environment.NewLine); center.MessagePublished msg Debug.WriteLine($[调试] {msg}); center.Publish(系统启动成功);运行后三个订阅者都会收到“系统启动成功”这就实现了观察者模式。发布者不需要知道订阅者具体是谁哪怕是后来加的第100个订阅者也不用改发布者代码。这正是当初那个订单项目重构后最想达到的效果。event Action 与 event Action 的分工如果用一个不带参数的 event Action消息中心只能告诉外部“有消息发布了”至于消息内容是什么还得去别的地方取。带 string 参数的版本则把内容本身打包进了事件参数里。平时写业务事件建议优先按“参数即承载物”来设计event Action像门铃响只关注“响了”这一事实。event Action 像来了一封短信不光知道“来了”还知道写了什么。如果以后要承载更复杂的结构体就把 string 换成对应的数据类比如 event Action 。原理完全一致只是参数类型不同。多播委托异常会中断链条这里有个绝大多数新手不知道的坑。事件背后是委托的多播调用列表默认是“一个接一个执行”。如果某个订阅者的处理方法抛了异常后面的订阅者全都不会再执行center.MessagePublished msg throw new Exception(第一条就炸了); center.MessagePublished msg Console.WriteLine(这条永不执行);运行后只看到异常第二条订阅者根本没机会执行。因为多播委托的 Invoke 是按列表顺序循环调用的任何一个节点抛异常整个调用就中断了。所以发布者不能用天然的多播委托一穿到底至少要评估订阅者的健壮性。用 GetInvocationList 逐个安全触发解决办法也很简单取委托的调用列表逐个遍历自己包 try-catch。public void Publish(string message) { if (MessagePublished null) { return; } foreach (Actionstring handler in MessagePublished.GetInvocationList()) { try { handler(message); } catch (Exception ex) { Console.WriteLine($订阅者执行失败{ex.Message}); } } }GetInvocationList() 返回的是一个 Delegate 数组每个元素就是一个订阅者方法。手动逐个调用并把每段逻辑隔离在 try-catch 里这样即使某一个订阅者炸了也只是记录一条错误不会影响其他订阅者。这个设计在写插件、脚本、消息总线时几乎是必选项。稳健的发布器不应该为一个订阅者的崩溃断电。重复订阅这个隐蔽问题还有一个很隐蔽的问题 同一个方法多次同一个订阅者会被执行多次center.MessagePublished OnMessage; center.MessagePublished OnMessage; // 发布时 OnMessage 会跑两次解决办法是订阅前先减去一次center.MessagePublished - OnMessage; center.MessagePublished OnMessage;这个方法很实用尤其是界面刷新、定时器重挂事件时能避免事件积少成多造成性能下降甚至逻辑错乱。如果实在担心忘记退订可以封装一个 Subscribe 方法内部自动执行“先减后加”。跨线程回调在 UI 程序里用 Action 的正确姿势委托和事件在后台线程配合 UI 的场景是最容易被绊倒的。比如一个串口程序后台线程不断收到数据希望通过 event Action 把数据交给界面刷新。为什么后台线程更新控件会抛异常WinForms 或 WPF 里UI 控件只能在 UI 线程上操作。后台线程尝试改控件的 Text 属性会抛 InvalidOperationException跨线程操作无效从不是创建控件的线程访问它。事件本身不会帮你切换线程订阅者在哪里执行取决于发布器是在哪个线程调用的 Invoke。发布器在后台线程所有订阅者就在后台线程执行。所以要么发布器负责调度线程要么订阅者自己切线程不能指望事件框架帮忙。用 SynchronizationContext 回到 UI 线程比较通用的做法是UI 侧在构造时捕获当前的同步上下文然后把回调塞回去public partial class MainForm : Form { private readonly SynchronizationContext _context; private readonly MessageCenter _center; public MainForm() { InitializeComponent(); _context SynchronizationContext.Current ?? new WindowsFormsSynchronizationContext(); _center new MessageCenter(); _center.MessagePublished msg { _context.Post(_ UpdateLabel(msg), null); }; } private void UpdateLabel(string msg) { lblMsg.Text msg; } }SynchronizationContext.Current 在 UI 线程获取到的就是“能把代码送回 UI 线程”的上下文。Post 表示异步投递不会阻塞发布器所在的线程。这样即使发布器在串口后台线程里调用事件订阅者最终也能安稳地回到 UI 线程执行。两套对应写法WinForms 与 WPF如果不想依赖 SynchronizationContext也可以直接用控件自己的调度器。WinForms_center.MessagePublished msg { lblMsg.BeginInvoke(new Action(() lblMsg.Text msg)); };WPF_center.MessagePublished msg { Dispatcher.BeginInvoke(() lblMsg.Text msg); };两个思路本质相同把更新动作转移给控件归属的线程执行。区别只在于调度API的名字。能理解这一点在哪个框架里都不慌。实际项目中我会更推荐 SynchronizationContext 的做法。因为界面层不关心具体是哪个控件只需要知道“我要回UI线程”上下文抽象了一层在单元测试里也很容易替换。面试脱口而出版委托与事件的区别怎么答“C#里什么是委托”“委托和事件什么关系”——这两道题面试出现频率极高。每次听到有人当场背诵定义我都能感觉到面试官不太买账。背定义不如讲结构。30秒版本委托是一种类型用来描述方法的签名委托的实例可以保存一个或多个方法然后在需要的时候调用。事件是建立在委托基础上、带有发布/订阅语义的受限委托外部只能通过 和 - 来订阅或退订不能直接触发也不能整体替换。3分钟版本设计意图加代码佐证先把一个最简单的发布器写在纸上public class Button { public event Action Click; public void OnClick() { Click?.Invoke(); } }然后解释Click 是一个事件外部说“我要订阅”就是用 你的方法事件被触发时也就是按钮内部调用 Invoke 时订阅的方法才会执行。这背后的关键是触发权的归属只有 Button 自己能决定什么时候触发 Click外部无法强行触发也无法把 Click 整个重置为别的方法。再补一个对比点去掉 event只写public Action Click;外部就能button.Click null;甚至button.Click();主动触发设计就崩了。所以事件不是语法噱头而是一种访问边界控制。别和前端“事件委托”混淆有一个概念坑是跨语言的。前端JavaScript里有个“事件委托”指的是利用DOM事件冒泡把子元素的事件处理交给父元素统一处理。这是完全不同的东西。C#的委托与事件是两个层面的概念委托一种方法类型/方法引用的容器。事件一种基于委托的发布/订阅机制。前端的“事件委托”一种利用事件冒泡的页面优化技巧。面试时如果被问“事件委托”先确认对方问的是C#里的 delegate/event还是DOM里的事件代理。把两者混在一起讲容易翻车。常见追问面试官经常追着问场景题比如“你要设计一个日志中心多个模块要订阅日志用事件还是回调”答案明显是事件。因为日志中心是中心化的发布方多个模块独立订阅而且不希望外部随便调用日志中心内部逻辑。这时public event Actionstring LogReceived;是最自然的模型。还有一个高频追问是“多播委托如何取返回值”。委托支持多个返回值但普通 Invoke 只返回最后一个方法的结果。完整做法是拿到 GetInvocationList() 逐个调用分别拿返回值Funcint[] handlers ...; // 类似思路 foreach (var handler in someMulticast.GetInvocationList()) { var result ((Funcint)handler)(); Console.WriteLine(result); }这条我已经在一线项目中见过太多次了回答出来很加分。这条路上我踩过的坑最后集中说几个长期实践中容易踩的坑每一个我都在真实项目里付出过代价。事件订阅导致的内存泄漏这是最阴的一个坑。事件从发布器引用着订阅者发布器是长期存在的单例或全局对象订阅者是临时创建的窗体连续打开关闭几十次旧窗体一直被事件源引用永远无法被垃圾回收。表现是内存只升不降。预防思路很直白临时订阅者在销毁时记得-退订。订阅方法里不持有大对象、长生命周期对象。实在不好管理的使用弱事件模式WeakEvent。如果用的是我们前面自定义的 add/remove还能顺手在 remove 里打一条日志排查泄漏时能直接定位。匿名 lambda 回调的移除问题很多新手写出来这样的代码center.MessagePublished msg Console.WriteLine(msg);后来想退订却找不到方法名。匿名 lambda 没有名字你不可能在另一个地方再把同一个匿名方法退订。正确做法是把回调方法单独声明成普通方法或者先用变量保存委托Actionstring handler msg Console.WriteLine(msg); center.MessagePublished handler; center.MessagePublished - handler;不是不能用 lambda而是用之前要想清楚“以后还需不需要退订”。需要退订的场景尽量不写匿名方法。async void 事件处理器的吞异常特性把事件处理器直接写成 async void 是C#里相当容易犯的错center.MessagePublished async msg { await Task.Delay(100); throw new Exception(炸了); };async void 方法的异常不会沿调用栈传回发布器而是直接进入线程池级的未观察异常处理相当于被悄悄吞掉了。如果你用 GetInvocationList 逐个 try-catch 也拦不住它因为异常出现在 await 后的异步上下文中。如果必须用异步处理器建议不要在事件处理器里直接抛异常显式捕获并记录日志才是稳妥方案。我个人现在的习惯是凡是设计对外发布的类一律用 event 而不是公开委托字段凡是发布器要支持大量订阅者一定用 GetInvocationList 做隔离凡是事件回调涉及UI更新第一时间考虑 SynchronizationContext而不是等运行时报了跨线程错误才去补救。这些习惯看起来不起眼真正把它们贯穿到每个项目里能帮你躲开一多半线上事故。

相关新闻

UUID版本选择指南:从v4随机到v7有序,数据库主键性能与选型深度解析

UUID版本选择指南:从v4随机到v7有序,数据库主键性能与选型深度解析

UUID 这个词很多人天天用,但真正理解它背后设计逻辑的开发者并不多。早几年我参与过一个模拟项目,主键图省事全部采用 UUID,上线三个月后数据库 INSERT 开始出现大量慢查询,DBA 排查后丢过来一句话:“你是 v4 吧&#…

2026/10/13 7:52:16 阅读更多 →
MES选型与实施指南:从业务梳理到AMR对接的完整路径

MES选型与实施指南:从业务梳理到AMR对接的完整路径

简介:制造执行系统(MES)选型与实施指南是一份面向制造企业CIO、信息化主管及智能制造咨询顾问的中文PDF文档,聚焦MES选型、功能需求梳理与落地实施中的常见困惑。资源为单份PDF文件,大小约1.7MB,已有2545人学习下载。内容章节完整…

2026/10/13 7:52:16 阅读更多 →
MySQL表结构查询全攻略:从DESC到information_schema的进阶实践

MySQL表结构查询全攻略:从DESC到information_schema的进阶实践

1. 从一条 SQL 聊起:为什么“看表结构”这件事值得写一篇长文 先问个问题:你在 MySQL 里想知道一张表长什么样,第一反应是敲什么命令?我猜八成是 DESC 或者 SHOW CREATE TABLE 。这两个确实最常用,但如果你只停留在…

2026/10/13 7:52:15 阅读更多 →

最新新闻

基于PaddleOCR与PyQt5的GUI车票识别系统设计与实现

基于PaddleOCR与PyQt5的GUI车票识别系统设计与实现

简介:这是一套基于GUI的OCR车票识别完整毕业设计项目,面向计算机视觉、机器学习方向的本科生及入门开发者,重点解决车票日期、车次、座位号等关键信息的自动提取与可视化操作问题。压缩包共82个文件,整体约4.01MB,包含…

2026/10/13 8:37:52 阅读更多 →
Prim算法详解:最小生成树的原理、实现与工程实践

Prim算法详解:最小生成树的原理、实现与工程实践

1. “Prime算法”到底在讲什么先把这个名字聊透。“Prime算法”在计算机与数据结构的语境下,最常被对应到两条线:一条是图论里求最小生成树的经典贪心算法——Prim算法,另一条则是素数(Prime Number)相关的数论算法&am…

2026/10/13 8:37:52 阅读更多 →
改限制不如改记录:AI内容安全审查记录实战解析

改限制不如改记录:AI内容安全审查记录实战解析

我先不跟你聊那些参数、榜单、跑分,最近这轮更新日志读下来,真正值得关心的变化往往藏在模型之外的“运行记录”里。不少团队把“每日AI观察”的焦点,从“这次又收紧了多少条限制规则”,转向了“审查记录到底长什么样”。我最近正…

2026/10/13 8:37:52 阅读更多 →
终端显示‘impeccable‘?揭秘CLI认证成功标识与误搜根源

终端显示‘impeccable‘?揭秘CLI认证成功标识与误搜根源

1. 项目概述:一个被误读的 CLI 工具命名现象最近在多个技术社区和开发者群聊里,频繁看到“impeccable”这个词被当作某个命令行工具的名称反复提及——它既不是 npm 官方包、也不是主流开源组织发布的 CLI,更没有对应的 GitHub 仓库或文档站。…

2026/10/13 8:37:52 阅读更多 →
UG/NX教程筛选与学习路径:从版本匹配到建模、加工实战

UG/NX教程筛选与学习路径:从版本匹配到建模、加工实战

简介:这是一份整理50套UG(Unigraphics NX)学习教程下载地址的PDF文档,面向使用UG进行产品设计、模具设计、逆向工程及数控加工的工程师和学员,旨在解决教程资源分散、难以系统查找的问题。文档收录了从UG NX4.0到NX7.5…

2026/10/13 8:37:52 阅读更多 →
视频目标跟踪标注工具VATIC非Docker安装全攻略

视频目标跟踪标注工具VATIC非Docker安装全攻略

如果你要做目标检测或者视频目标跟踪,第一步往往不是调模型,而是先把训练数据准备好。标注一个视频里每个目标每一帧的位置,听起来不复杂,真做起来又磨人又容易出错。VATIC 就是干这个的开源视频标注工具:打开浏览器&a…

2026/10/13 8:36:51 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →