C# 如何等候多個EventHandler的事件

weixin_44220506 2021-02-01 11:25:35
假設有一主程式,主程式分別會提供資料給兩個dll,這兩個dll各自有eventhandler,並由主程式註冊副程式,當副程式被呼叫時代表dll返回的異步結果。 希望兩個異步結果是能夠匹配的,請問應該怎麼做才好呢?謝謝大家。
...全文
872 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
qcjlxh 2021-02-03
  • 打赏
  • 举报
回复
学习学习学习
PLC云峰. 2021-02-03
  • 打赏
  • 举报
回复
求叻:R[0],R[1]。。。。。R[n] 如何C#语言初始化 数组n,数组最小值,数组最大值都可设定。
PLC云峰. 2021-02-03
  • 打赏
  • 举报
回复
引用 楼主 weixin_44220506的回复:
假設有一主程式,主程式分別會提供資料給兩個dll,這兩個dll各自有eventhandler,並由主程式註冊副程式,當副程式被呼叫時代表dll返回的異步結果。 希望兩個異步結果是能夠匹配的,請問應該怎麼做才好呢?謝謝大家。
求叻:R[0],R[1]。。。。。R[n] 如何C#语言初始化 数组n,数组最小值,数组最大值都可设定。
PLC云峰. 2021-02-03
  • 打赏
  • 举报
回复
求助:R[0],R[1],。。。R[n]。 取值范围:0.2---6.0 数组n可设定,最小值可设定,最大值可设定 这个数组如何初始化?
weixin_44220506 2021-02-03
  • 打赏
  • 举报
回复
預備結帖了 謝謝大家!!!
weixin_44220506 2021-02-03
  • 打赏
  • 举报
回复
引用 18 楼 datafansbj 的回复:
给你一个适用于高性能的思路(不是循环等待,而是使用 ManualResetEvent):


謝謝分享哦,和Win32的WaitForMultipleObjects相同的工具 :)
weixin_44220506 2021-02-03
  • 打赏
  • 举报
回复
引用 17 楼 wanghui0380 的回复:
还有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
(虽然那个园子俺们觉着已经丧失意义了,但张队还是张队,张队的文章还是可以看的)


謝謝您的解說,獲得新的工具能使用了^^
weixin_44220506 2021-02-02
  • 打赏
  • 举报
回复
引用 6 楼 datafansbj 的回复:
由于是异步的调用,所以两个结果是在两个线程返回的,需要同步。可使用信号量来处理,参见 https://www.cnblogs.com/forever-ys/p/11675953.html


A dll Callback(結果)
{
設定信號量
}

B dll Callback(結果)
{
設定信號量
}


某Thread While Loop
{
檢查是否有收到A及B的信號量,有的話才往下,否則阻塞。

}


我想的大概是這樣子。請問正確嗎? 是否會有缺點呢?
weixin_44220506 2021-02-02
  • 打赏
  • 举报
回复
引用 5 楼 shawn_yang 的回复:
两个都得到反馈再返回啊,否则一直等待


就是不曉得兩個異步callback的結果要怎麼等待,
請問要用什麼工具呢? 煩請賜教哦,謝謝。
datafansbj 2021-02-02
  • 打赏
  • 举报
回复
由于是异步的调用,所以两个结果是在两个线程返回的,需要同步。可使用信号量来处理,参见 https://www.cnblogs.com/forever-ys/p/11675953.html
shawn_yang 2021-02-02
  • 打赏
  • 举报
回复
两个都得到反馈再返回啊,否则一直等待
weixin_44220506 2021-02-02
  • 打赏
  • 举报
回复
引用 1 楼 datafansbj 的回复:
“匹配”是什么意思?


同一個輸入會丟到兩個分別的黑盒子內,黑盒子會採用CALLBACK的方式回覆,但兩個黑盒子的回覆時間可能不一定,
但又希望將兩個黑盒子的回覆資訊整合。

請問這樣能理解嗎?
gs0038 2021-02-02
  • 打赏
  • 举报
回复
没看懂意思123
shawn_yang 2021-02-02
  • 打赏
  • 举报
回复
没看懂意思???
datafansbj 2021-02-02
  • 打赏
  • 举报
回复
“匹配”是什么意思?
datafansbj 2021-02-02
  • 打赏
  • 举报
回复
给你一个适用于高性能的思路(不是循环等待,而是使用 ManualResetEvent):
wanghui0380 2021-02-02
  • 打赏
  • 举报
回复
还有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 (虽然那个园子俺们觉着已经丧失意义了,但张队还是张队,张队的文章还是可以看的)
weixin_44220506 2021-02-02
  • 打赏
  • 举报
回复
引用 12 楼 wanghui0380 的回复:
哎,我们还是展示一下现代的做法把

现在手段有很多,我选择响应式编程(可观察数据源)方式完成
先上代码
  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结对组合发给你


謝謝分享!!! 原來還有這樣的東西@@ 這看起來是我要的,感覺複雜的計算RX.Net都處理掉了。

請問除了Rx.Net外,還有什麼不錯的手段呢? 還請您不吝分享,謝謝:)
weixin_44220506 2021-02-02
  • 打赏
  • 举报
回复
引用 11 楼 datafansbj 的回复:
你这里有两个回调函数,分别在两个线程执行,使用信号量不太好处理。最简单的方法就是使用两个全局变量做标识,两个回调函数执行完毕后分别修改对应全局变量的标识值,然后主线程在调用两个 dll 后,使用类似 while(true) { ...... Thread.Sleep(10) } 的结构来判断全局变量的值。这样逻辑比较简单,结构也清晰,只是效率低了一些,不过在不需要高性能的场景下足够了。


在這裡主線程會不停的送同一份資料給這兩個dll的函式,也會不停的拿到結果,希望儘可能的不要等待,需要高性能使用。
wanghui0380 2021-02-02
  • 打赏
  • 举报
回复
rx是一组响应式操作,当然操作符不止zip一种,所以我们愿意给你推荐 当然如果你一定要自己的,其实把图看一眼,也瞬间明了 传统上我们使用状态机 当然问题比较特殊,我们就是使用两个队列保存值 任何一个事件到达 都把自己先加到对应队列 然后在去检测一下,两个队列的count是否都>1 如果都大于1就分别出一个元素(状态判定-都达到) 如果有队列数据count是0,就不组合数据(状态判定--未达到状态迁移条件,不执行组合动作)
加载更多回复(4)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧