首页 > 基础资料 博客日记
AScript异步执行与await关键字
2026-05-21 20:00:02基础资料围观15次
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 关键字来异步调用方法及传递取消令牌并等待结果。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:

