diff --git a/HW-Async&Thread-1/Program.cs b/HW-Async&Thread-1/Program.cs index 6965f01..9a63bd7 100644 --- a/HW-Async&Thread-1/Program.cs +++ b/HW-Async&Thread-1/Program.cs @@ -1,125 +1,149 @@ -namespace HW_Async_Thread; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; -public class Program +namespace HW_Async_Thread { - public static void Main() + public class Program { - // 测试用例: (a + b) + (c + d) - // 可以自行修改测试用例 - ValueExpr a = new(1); - ValueExpr b = new(2); - ValueExpr c = new(3); - ValueExpr d = new(4); - AddExpr add1 = new(a, b); - AddExpr add2 = new(c, d); - AddExpr add3 = new(add1, add2); - Console.WriteLine(add3.Val); - a.NewVal = 5; - Console.WriteLine(add3.Val); - } -} + public static async Task Main() + { + // 测试用例: (a + b) + (c + d) + ValueExpr a = new ValueExpr(1); + ValueExpr b = new ValueExpr(2); + ValueExpr c = new ValueExpr(3); + ValueExpr d = new ValueExpr(4); + AddExpr add1 = new AddExpr(a, b); + AddExpr add2 = new AddExpr(c, d); + AddExpr add3 = new AddExpr(add1, add2); -/// -/// 表达式结点抽象类,用于构造表达式树 -/// -public abstract class Expr -{ - /// - /// 父结点 - /// - protected Expr? parent = null; - - /// - /// 表达式的值,只允许返回一个现成的值,可以加锁 - /// 拓展思考:是否所有时候读取到的值都是其正确的值?如何避免? - /// - public abstract int Val { get; } - - /// - /// 异步方法,它的作用是启动一个任务,推动结点自身及其父结点更新值 - /// 可以根据自身需求适当修改方法签名 - /// - public abstract Task Update(); - - /// - /// 注册父结点 - /// 思考:当父结点被注册后,父结点的值是否需要更新? - /// - /// 待注册的父结点 - public abstract void Register(Expr parent); -} -/// -/// 数据结点 -/// -/// 初始值 -public class ValueExpr(int initVal) : Expr -{ - int val = initVal; - public override int Val - { - get - { - // TODO 1:读取操作 - return val; + Console.WriteLine(await add3.Val); + + a.NewVal = 5; + await add3.Update(); + + + Console.WriteLine(await add3.Val); } } - /// - /// 修改数据 - /// 思考:修改数据后,父结点是否也需要更新? - /// - public int NewVal + public abstract class Expr { - set + protected readonly List parents = new List(); + private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); + protected bool isDirty = true; + + public abstract Task GetValAsync(); + + public Task Val { - // TODO 2:修改操作 + get + { + return GetValAsync(); + } } - } - public override async Task Update() - { - // TODO 3:更新操作 - } + public abstract Task Update(); - public override void Register(Expr parent) - { - // TODO 4:注册操作 - } -} + public abstract void Register(Expr parent); -/// -/// 加法表达式结点 -/// 可以根据自己的想法创造更多种类的结点 -/// -public class AddExpr : Expr -{ - int val = 0; - public override int Val - { - get + protected void NotifyParents() { - // TODO 5:读取操作 - return val; + foreach (var parent in parents) + { + _ = parent.Update(); + } } - } - public Expr ExprA, ExprB; - public AddExpr(Expr A, Expr B) - { - ExprA = A; - ExprB = B; - A.Register(this); - B.Register(this); + protected async Task WaitForUpdate() + { + await semaphore.WaitAsync(); + try + { + await Update(); + } + finally + { + semaphore.Release(); + } + } } - public override async Task Update() + public class ValueExpr : Expr { - // TODO 6:更新操作 + private int val; + + public ValueExpr(int initVal) + { + val = initVal; + } + + public override Task GetValAsync() + { + return Task.FromResult(val); + } + + public int NewVal + { + set + { + if (val != value) + { + val = value; + NotifyParents(); + } + } + } + + public override Task Update() + { + return Task.CompletedTask; + } + + public override void Register(Expr parent) + { + parents.Add(parent); + } } - public override void Register(Expr parent) + public class AddExpr : Expr { - // TODO 7:注册操作 + private int val; + private readonly Expr exprA; + private readonly Expr exprB; + + public AddExpr(Expr A, Expr B) + { + exprA = A; + exprB = B; + A.Register(this); + B.Register(this); + } + + public override async Task GetValAsync() + { + if (isDirty) + { + await WaitForUpdate(); + } + return val; + } + + public override async Task Update() + { + await Task.WhenAll(exprA.GetValAsync(), exprB.GetValAsync()); + val = await exprA.GetValAsync() + await exprB.GetValAsync(); + isDirty = false; + NotifyParents(); + } + + public override void Register(Expr parent) + { + parents.Add(parent); + } } } + +