假設有一主程式,主程式分別會提供資料給兩個dll,這兩個dll各自有eventhandler,並由主程式註冊副程式,當副程式被呼叫時代表dll返回的異步結果。 希望兩個異步結果是能夠匹配的,請問應該怎麼做才好呢?謝謝大家。
给你一个适用于高性能的思路(不是循环等待,而是使用 ManualResetEvent):
还有Dataflow Tpl方式,当然你在nuget上搜索状态机方面的东西也行 状态机,响应式编程,复合事务处理都是解决这类问题的封装 后面的我就不给代码了,直接给相关的资料 1.Dataflow Tpl 方式的(按你的要求,可以使用JoinBlock完成) https://www.cnblogs.com/dinggf/p/9294613.html 2.复合事务处理(CEP) https://www.cnblogs.com/shanyou/category/262009.html (虽然那个园子俺们觉着已经丧失意义了,但张队还是张队,张队的文章还是可以看的)
由于是异步的调用,所以两个结果是在两个线程返回的,需要同步。可使用信号量来处理,参见 https://www.cnblogs.com/forever-ys/p/11675953.html
两个都得到反馈再返回啊,否则一直等待
“匹配”是什么意思?
哎,我们还是展示一下现代的做法把 现在手段有很多,我选择响应式编程(可观察数据源)方式完成 先上代码 static async Task Main(string[] args) { //展示rx响应的过程 TestA _testA=new TestA(); var ASrouce=Observable.FromEvent<(DateTime, string)>(p=>_testA.testAEvent+=p,p=>_testA.testAEvent-=p); var BSrouce = Observable.FromEvent<(DateTime, string)>(p => _testA.testBEvent += p, p => _testA.testBEvent -= p); // 分别展示两个事件数据源到达时间 ASrouce.Subscribe(p => { Console.WriteLine($"事件A到达{p.Item1}"); }); BSrouce.Subscribe(p => { Console.WriteLine($"事件B到达{p.Item1}"); }); ASrouce.Zip(BSrouce).Subscribe(p => { Console.WriteLine($"A,B都已到达:[{p.First.Item2}_{p.First.Item1}][{p.Second.Item2}_{p.Second.Item1}]"); }); //启动数据模拟 _testA.start(); Console.ReadKey(); } class TestA { public event Action<(DateTime,string)> testAEvent; public event Action<(DateTime, string)> testBEvent; //制作一个模拟过程定义两个事件,定时调用一下两个事件(为了展示他们不同时到达,所以我分别以不同的频率去调用) public void start() { Task.Factory.StartNew(async () => { while (true) { testAEvent?.Invoke((DateTime.Now, "testA")); await Task.Delay(200); } }); Task.Factory.StartNew(async () => { while (true) { testBEvent?.Invoke((DateTime.Now, "testB")); await Task.Delay(500); } }); } } 代码本身我就不说啥了,RX.net的基本使用方式。至于他的效果,直接上图 看看是不是你要求的,无论A,B怎么顺序到达,他自动按1对1结对组合发给你
static async Task Main(string[] args) { //展示rx响应的过程 TestA _testA=new TestA(); var ASrouce=Observable.FromEvent<(DateTime, string)>(p=>_testA.testAEvent+=p,p=>_testA.testAEvent-=p); var BSrouce = Observable.FromEvent<(DateTime, string)>(p => _testA.testBEvent += p, p => _testA.testBEvent -= p); // 分别展示两个事件数据源到达时间 ASrouce.Subscribe(p => { Console.WriteLine($"事件A到达{p.Item1}"); }); BSrouce.Subscribe(p => { Console.WriteLine($"事件B到达{p.Item1}"); }); ASrouce.Zip(BSrouce).Subscribe(p => { Console.WriteLine($"A,B都已到达:[{p.First.Item2}_{p.First.Item1}][{p.Second.Item2}_{p.Second.Item1}]"); }); //启动数据模拟 _testA.start(); Console.ReadKey(); } class TestA { public event Action<(DateTime,string)> testAEvent; public event Action<(DateTime, string)> testBEvent; //制作一个模拟过程定义两个事件,定时调用一下两个事件(为了展示他们不同时到达,所以我分别以不同的频率去调用) public void start() { Task.Factory.StartNew(async () => { while (true) { testAEvent?.Invoke((DateTime.Now, "testA")); await Task.Delay(200); } }); Task.Factory.StartNew(async () => { while (true) { testBEvent?.Invoke((DateTime.Now, "testB")); await Task.Delay(500); } }); } }
你这里有两个回调函数,分别在两个线程执行,使用信号量不太好处理。最简单的方法就是使用两个全局变量做标识,两个回调函数执行完毕后分别修改对应全局变量的标识值,然后主线程在调用两个 dll 后,使用类似 while(true) { ...... Thread.Sleep(10) } 的结构来判断全局变量的值。这样逻辑比较简单,结构也清晰,只是效率低了一些,不过在不需要高性能的场景下足够了。
110,538
社区成员
642,577
社区内容
加载中
让您成为最强悍的C#开发者
试试用AI创作助手写篇文章吧