惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
Microsoft Azure Blog
Microsoft Azure Blog
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
Martin Fowler
Martin Fowler
B
Blog
The GitHub Blog
The GitHub Blog
T
Tailwind CSS Blog
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
DataBreaches.Net
月光博客
月光博客
人人都是产品经理
人人都是产品经理
IT之家
IT之家
GbyAI
GbyAI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
博客园 - Franky
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
C
Check Point Blog
罗磊的独立博客

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解
AScript异步执行与await关键字
rockey627 · 2026-05-21 · via 博客园_首页

AScript是一个开源的C#动态脚本解析执行引擎,从1.2.5版本开始支持异步解析执行以及新增 await 和 @@CancellationToken 关键字。

一、异步解析执行

AScript提供了 Script.EvalAsync 异步方法,异步执行脚本,可设置 CancellationToken 参数。

AScript执行模式有解析执行和编译执行两种模式,这两种模式下的异步执行又有所不同:

1)解析执行模式:异步解析,异步执行,并且异步执行脚本中 await 后面的方法;

2)编译执行模式:异步解析,同步编译,同步执行,脚本中 await 后面的方法则会调用 Task.Wait() 或者 Task<T>.Result 来等待完成。

示例:

1 var script = new Script();
2 // 100毫秒超时
3 var cts = new CancellationTokenSource(100);
4 // 异步读取脚本文件,异步解析脚本,异步执行脚本,如果超时100毫秒则报OperationCanceledException异常
5 var result = await script.EvalAsync(File.OpenRead("mycode.txt"), cancellationToken: cts.Token);
6 Console.WriteLine($"value:{result.Value}, type:{result.Type}");

二、await关键字

脚本中调用异步方法并等待完成,使用 await 关键字,当然也可以直接调用 Task.Wait() 或者 Task<T>.Result 来等待完成,为什么推荐使用 await 呢?

1)异步执行时,脚本中的方法也是异步的;

2)同步执行时,等效于 Task.Wait() 或者 Task<T>.Result ;

3)如果 await 后面的方法不是异步方法,则自动忽略 await ;

所以脚本中使用 await 关键字更省心更安全。

示例:

 1 Func<int, int, Task<int>> sum = async (a, b) =>
 2 {
 3     await Task.Delay(1000);
 4     return a + b;
 5 };
 6 string s = @"
 7 var a = await sum(5, 10);
 8 await Task.Delay(500);
 9 a + 20
10 ";
11 var script = new Script();
12 script.Context.AddFunc("sum", sum);
13 // 异步执行
14 var result = await script.EvalAsync(s);
15 Assert.AreEqual(35, result.Value);
16 Assert.AreEqual(typeof(int), result.Type);
17 // 同步执行,等效于:var a = sum(5, 10).Result; Task.Delay(500).Wait(); a + 20
18 Assert.AreEqual(35, script.Eval(s));

 await 关键字实现原理请查看源码 AScript.TokenHandlers.AwaitTokenHandler 和 AScript.Functions.AwaitFunction 。

三、@@CancellationToken关键字

1)异步执行时,值为 EvalAsync 方法参数中的 CancellationToken ;

2)同步执行时,值为 CancellationToken.None 。

示例:

1 var script = new Script();
2 // 100毫秒超时
3 var cts = new CancellationTokenSource(100);
4 await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
5 {
6     await script.EvalAsync("await Task.Delay(1000, @@CancellationToken)", cancellationToken: cts.Token);
7 });

实现原理:

 1 public class CancellationTokenHandler : ITokenHandler, IAsyncTokenHandler
 2 {
 3     public static readonly CancellationTokenHandler Instance = new CancellationTokenHandler();
 4 
 5     public void Build(DefaultSyntaxAnalyzer analyzer, TokenAnalyzingArgs e)
 6     {
 7         e.IsHandled = true;
 8         if (!e.Ignore)
 9         {
10             e.TreeBuilder.AddData(e.BuildContext, e.ScriptContext, e.Options, e.Control, CancellationToken.None);
11         }
12     }
13 
14     public async Task BuildAsync(DefaultSyntaxAnalyzer analyzer, TokenAnalyzingArgs e, CancellationToken cancellationToken)
15     {
16         e.IsHandled = true;
17         if (!e.Ignore)
18         {
19             e.TreeBuilder.AddData(e.BuildContext, e.ScriptContext, e.Options, e.Control, cancellationToken);
20         }
21     }
22 }

在 CSharpLang 中注册: AddTokenHandler("@@CancellationToken", CancellationTokenHandler.Instance); 

四、总结

AScript提供了 EvalAsync 方法来异步读取、解析、执行脚本;

脚本中使用 await 和 @@CancellationToken 关键字来异步调用方法及传递取消令牌并等待结果。

开源地址:https://gitee.com/rockey627/AScript