gpt4 book ai didi

c# - 如何同步事件处理程序

转载 作者:太空宇宙 更新时间:2023-11-03 18:16:51 24 4
gpt4 key购买 nike

多线程仍在我的工作 list 上,因此标题可能是完全错误的:)

我的对象正在监听串行端口,如下所示:

class MyClass
{
MyOpticalScanner _scanner;

public MyClass()
{
_scanner = new MyOpticalScanner();
_scanner.CodeScanned += CodeScannedEventHandler;
}

private void CodeScannedEventHandler(object sender, CodeScannedEventArgs e)
{
Debug.WriteLine("ThreadID: " + Thread.CurrentThread.ManagedThreadId + " ||| " + e.ScannedCode);
....
// Some code, query the database, etc...
}
}

扫描程序正在发送有序数据: 001002003004005,...。但是,如果CodeScannedEventHandler中的代码处理时间太长,则会引发另一个事件,并且我得到不一致的排序。事件处理程序中的 Debug.WriteLine可以给我以下信息:
ThreadID: 8 ||| 001
ThreadID: 9 ||| 002
ThreadID: 10 ||| 003
ThreadID: 10 ||| 006
ThreadID: 8 ||| 004
ThreadID: 8 ||| 008
ThreadID: 8 ||| 009
ThreadID: 8 ||| 010
ThreadID: 10 ||| 007
ThreadID: 9 ||| 005

我如何确保每个新事件仅在旧事件结束后才开始处理?

编辑1-我没有告诉您所有信息,实际上我在测试过程中没有在听COM端口,而是创建了自己的模拟对象。该对象(ScannerMock)使用内部System.Timer并在Timer.OnTick事件上引发CodeScanned事件。问题出在这里吗?

根据 Hans Passant's answer中的注释:SerialPort具有一个内部锁,该锁可确保DataReceived事件在运行时不会再次被调用。我应该在模拟扫描仪中包括类似的锁吗?如何?

编辑2:我向扫描仪对象添加了一个锁,并将引发事件的代码放入其中。看起来很有效:)

最佳答案

如果CodeScannedEventHandler在上一个完成运行之前再次运行,则会遇到很大的问题。串行端口不执行此操作,它的DataReceived事件已序列化。锁不能可靠地解决此问题,不能保证线程获得锁的顺序。这就是您所看到的情况,Debug.WriteLine()内部有一个锁。

如果顺序确实很重要,那么您所能做的就是使事件处理程序尽可能短且活泼,因此它总是比事件运行的时间花费更少的时间。快速将扫描结果存储在线程安全的队列中并退出。您需要另一个清空队列的线程。它仍然不是100%的保证,您需要得到MyOpticalScanner撰写者的帮助才能获得该保证。

关于c# - 如何同步事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4946508/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com