搜索
bottom↓
回复: 21
打印 上一主题 下一主题

VS请教两个线程同时运行,如何保证两个线程内数据不丢包

[复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2023-4-30 00:17:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用EnterCriticalSection(cs)/LeaveCriticalSection(cs),也没能解决数据丢包现象。
线程A
while(1)
{
        EnterCriticalSection(cs);
        data0send_and_receive();
        LeaveCriticalSection(cs);
}

线程B
while(1)
{
        EnterCriticalSection(cs);
        data1send_and_receive();
        LeaveCriticalSection(cs);
}

出0入442汤圆

2
发表于 2023-4-30 00:18:49 来自手机 | 只看该作者
不要用criticalsection。。这玩意调度非常不稳定,有的撑死有的饿死。老老实实用mutex。

出200入2554汤圆

3
发表于 2023-4-30 01:20:36 | 只看该作者
问题在于:while1 里边没用 sleep(0)

线程这样基本不会释放 CPU,稍多就卡

出0入0汤圆

4
 楼主| 发表于 2023-4-30 08:26:03 来自手机 | 只看该作者
t3486784401 发表于 2023-4-30 01:20
问题在于:while1 里边没用 sleep(0)

线程这样基本不会释放 CPU,稍多就卡

(引用自3楼)

有Sleep,还是丢包

出590入992汤圆

5
发表于 2023-4-30 10:46:18 来自手机 | 只看该作者
我不太懂,我的理解是,不同线程不知道什么时候启动。所以设计上就得考虑?我之前设计的就是,如果两个线程都用,其中一个会设置一个标志位。
还有就是:线程锁?

出200入2554汤圆

6
发表于 2023-4-30 11:54:24 | 只看该作者
zw_7627 发表于 2023-4-30 08:26
有Sleep,还是丢包
(引用自4楼)

应该着重检查为何丢包吧? 例如数据处理不及时。

目前限定在临界区,总觉着可能南辕北辙。

出105入79汤圆

7
发表于 2023-4-30 13:32:38 | 只看该作者
什么包? UDP包还是UART包 ?

出0入0汤圆

8
 楼主| 发表于 2023-5-1 07:45:10 | 只看该作者
SUPER_CRJ 发表于 2023-4-30 10:46
我不太懂,我的理解是,不同线程不知道什么时候启动。所以设计上就得考虑?我之前设计的就是,如果两个线程 ...
(引用自5楼)

线程在初始化处就启动了,类似下面的结构:
while(1)
{
        WaitForSingleObject();
        EnterCriticalSection(&UdsStru_Can0.TxCs);
        data0sendandreceive();
        LeaveCriticalSection(&UdsStru_Can0.TxCs);
}

出0入0汤圆

9
 楼主| 发表于 2023-5-1 07:46:15 | 只看该作者
t3486784401 发表于 2023-4-30 11:54
应该着重检查为何丢包吧? 例如数据处理不及时。

目前限定在临界区,总觉着可能南辕北辙。 ...
(引用自6楼)

是的,应该是数据处理不及时。可能是WaitForSingleObject,没有进行原子处理。

出0入0汤圆

10
 楼主| 发表于 2023-5-1 07:46:39 | 只看该作者
qwe2231695 发表于 2023-4-30 13:32
什么包? UDP包还是UART包 ?
(引用自7楼)

UDS通信协议

出0入0汤圆

11
 楼主| 发表于 2023-5-1 07:55:26 | 只看该作者
wye11083 发表于 2023-4-30 00:18
不要用criticalsection。。这玩意调度非常不稳定,有的撑死有的饿死。老老实实用mutex。 ...
(引用自2楼)

mutex A_LOCK;
A_LOCK.lock();
dosomethings;
A_LOCK.unlock();
这样也不行。

出300入477汤圆

12
发表于 2023-5-1 11:43:40 来自手机 | 只看该作者
现在的电脑程序,通常CPU都是过剩的,用锁只是基于逻辑上的原因。如果你的两个线程没有共享什么东西,用锁没什么意义。只是把原来能跑满两个CPU的工作量变成了两者合起来只能用满一个CPU而已。
你应该说岀你的两个线程内部在做什么事,别人才好告诉你怎么实现是最佳做法。

出0入0汤圆

13
发表于 2023-5-1 15:18:55 | 只看该作者
描述太模糊了,你得把场景说清楚。

出0入0汤圆

14
 楼主| 发表于 2023-5-2 23:04:26 | 只看该作者
redroof 发表于 2023-5-1 11:43
现在的电脑程序,通常CPU都是过剩的,用锁只是基于逻辑上的原因。如果你的两个线程没有共享什么东西,用锁 ...
(引用自12楼)

线程A,处理CAN通道0数据,线程B处理CAN通道1数据。单独运行一个通道,程序稳定工作。两路通道同时运行,A或B会停止。结构如下:
while(1)
{
        waitsingleobject();
        senddata0;
        waitsingleobject();
        while(1)
        {
                Sleep(0);
                sendandreceive();
        }

}

出200入2554汤圆

15
发表于 2023-5-3 01:20:55 来自手机 | 只看该作者
zw_7627 发表于 2023-5-2 23:04
线程A,处理CAN通道0数据,线程B处理CAN通道1数据。单独运行一个通道,程序稳定工作。两路通道同时运行, ...
(引用自14楼)


写两个exe,每个exe只开一个线程,但exe1访问0通道,exe2访问1通道。

从系统进程一级,看是否还会造成卡死。

理论上进程一级已经很完善,这要都能卡死说明硬件限制,双开很可能就不支持

出300入477汤圆

16
发表于 2023-5-3 08:49:02 来自手机 | 只看该作者
本帖最后由 redroof 于 2023-5-3 08:50 编辑
zw_7627 发表于 2023-5-2 23:04
线程A,处理CAN通道0数据,线程B处理CAN通道1数据。单独运行一个通道,程序稳定工作。两路通道同时运行, ...
(引用自14楼)


通迅读写数据的底层函数,内部应该是自带阻塞等待的吧?
你外面的waitforsingleobject用来等待什么?
你自己做了双线程一个管收一个管发?

出0入0汤圆

17
发表于 2023-5-3 10:42:24 | 只看该作者
.net平台有个线程安全队列类ConcurrentQueue,不用加锁之类的。非常好用

出0入0汤圆

18
 楼主| 发表于 2023-5-3 10:44:54 | 只看该作者
t3486784401 发表于 2023-5-3 01:20
写两个exe,每个exe只开一个线程,但exe1访问0通道,exe2访问1通道。

从系统进程一级,看是否还会造成卡 ...
(引用自15楼)

双开是支持的。另一个工程里用sendandreceive是没有问题的。说明硬件没问题。
写两个EXE,每个EXE只开一个线程。这个实现不了,原因是盒子只能打开一次,在另一个EXE里打开,会报连接失败。

出0入0汤圆

19
 楼主| 发表于 2023-5-3 10:48:39 | 只看该作者
wurst 发表于 2023-5-3 10:42
.net平台有个线程安全队列类ConcurrentQueue,不用加锁之类的。非常好用
(引用自17楼)

C++

出300入477汤圆

20
发表于 2023-5-3 12:22:19 来自手机 | 只看该作者
zw_7627 发表于 2023-5-3 10:48
C++
(引用自19楼)

你先回答我的问题啊,你外面自己wait,是在等待什么东西?
CAN通迅底层函数难道不是自带阻塞的吗?
你调用can recv,如果读不到数据,应该自动挂起,直到你要的数据收到,或者超时返回错误。
用两个线程分别处理两个单独的通迅口,正常的程序结构根本不用加任何锁,各管各就行。
除非你所谓的两个通道在底层是同一个通迅口,根本不允许同时对两个通道收发数据。那你的程序结构就完全不一样了。

出0入0汤圆

21
 楼主| 发表于 2023-5-3 12:47:36 | 只看该作者
redroof 发表于 2023-5-3 12:22
你先回答我的问题啊,你外面自己wait,是在等待什么东西?
CAN通迅底层函数难道不是自带阻塞的吗?
你调 ...
(引用自20楼)

1、外面的wait是,等待接收信号处理;
2、收发线程带阻塞处理;
3、一个管收一个管发,收发是单独线程;
用两个线程分别处理两个单独的通迅口,正常的程序结构根本不用加任何锁,各管各就行。是的,在另一个工程里,同时对两个通道收发数据是正常的。
根据测试反馈的信息,发现A 或B总是停在waitsingleobject();语句后面。大部分是超时提示。

出300入477汤圆

22
发表于 2023-5-3 13:04:23 来自手机 | 只看该作者
zw_7627 发表于 2023-5-3 12:47
1、外面的wait是,等待接收信号处理;
2、收发线程带阻塞处理;
3、一个管收一个管发,收发是单独线程;

(引用自21楼)

外面的wait在等待接收到的信号,那就是你贴岀来的程序不全啊,发岀这个信号的那一部分程序也得贴岀来。
其实已经可以猜到这是跟同步对象有关的逻辑问题了。用了这些东西,要想清楚为什么要这样用。最好是画个流程图,画清楚哪里要等待信号,哪里负责发岀信号。。。。
或者,如果底层收发函数自带阻塞,你完全可以用最简单的程序结构,每个端口只用一个线程,发命令,阻塞收,处理,然后继续发。这样岀错概率更低。收发分离靠事件来互相通知的程序结构,确实是比较复杂的,如果不是非常需要高性能的场合,没必要这样做。can最就也就1兆bps,差不多100K字节每秒,阻塞式操作完全够。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-30 21:45

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表