zw_7627 发表于 2023-4-30 00:17:18

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

使用EnterCriticalSection(cs)/LeaveCriticalSection(cs),也没能解决数据丢包现象。
线程A
while(1)
{
        EnterCriticalSection(cs);
        data0send_and_receive();
        LeaveCriticalSection(cs);
}

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

wye11083 发表于 2023-4-30 00:18:49

不要用criticalsection。。这玩意调度非常不稳定,有的撑死有的饿死。老老实实用mutex。

t3486784401 发表于 2023-4-30 01:20:36

问题在于:while1 里边没用 sleep(0)

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

zw_7627 发表于 2023-4-30 08:26:03

t3486784401 发表于 2023-4-30 01:20
问题在于:while1 里边没用 sleep(0)

线程这样基本不会释放 CPU,稍多就卡
(引用自3楼)

有Sleep,还是丢包

SUPER_CRJ 发表于 2023-4-30 10:46:18

我不太懂,我的理解是,不同线程不知道什么时候启动。所以设计上就得考虑?我之前设计的就是,如果两个线程都用,其中一个会设置一个标志位。
还有就是:线程锁?

t3486784401 发表于 2023-4-30 11:54:24

zw_7627 发表于 2023-4-30 08:26
有Sleep,还是丢包
(引用自4楼)

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

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

qwe2231695 发表于 2023-4-30 13:32:38

什么包? UDP包还是UART包 ?

zw_7627 发表于 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);
}

zw_7627 发表于 2023-5-1 07:46:15

t3486784401 发表于 2023-4-30 11:54
应该着重检查为何丢包吧? 例如数据处理不及时。

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

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

zw_7627 发表于 2023-5-1 07:46:39

qwe2231695 发表于 2023-4-30 13:32
什么包? UDP包还是UART包 ?
(引用自7楼)

UDS通信协议

zw_7627 发表于 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();
这样也不行。

redroof 发表于 2023-5-1 11:43:40

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

御风逍遥Fly 发表于 2023-5-1 15:18:55

描述太模糊了,你得把场景说清楚。

zw_7627 发表于 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();
        }

}

t3486784401 发表于 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通道。

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

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

redroof 发表于 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用来等待什么?
你自己做了双线程一个管收一个管发?

wurst 发表于 2023-5-3 10:42:24

.net平台有个线程安全队列类ConcurrentQueue,不用加锁之类的。非常好用

zw_7627 发表于 2023-5-3 10:44:54

t3486784401 发表于 2023-5-3 01:20
写两个exe,每个exe只开一个线程,但exe1访问0通道,exe2访问1通道。

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

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

zw_7627 发表于 2023-5-3 10:48:39

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

C++{:handshake:}

redroof 发表于 2023-5-3 12:22:19

zw_7627 发表于 2023-5-3 10:48
C++
(引用自19楼)

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

zw_7627 发表于 2023-5-3 12:47:36

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

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

redroof 发表于 2023-5-3 13:04:23

zw_7627 发表于 2023-5-3 12:47
1、外面的wait是,等待接收信号处理;
2、收发线程带阻塞处理;
3、一个管收一个管发,收发是单独线程;

(引用自21楼)

外面的wait在等待接收到的信号,那就是你贴岀来的程序不全啊,发岀这个信号的那一部分程序也得贴岀来。
其实已经可以猜到这是跟同步对象有关的逻辑问题了。用了这些东西,要想清楚为什么要这样用。最好是画个流程图,画清楚哪里要等待信号,哪里负责发岀信号。。。。
或者,如果底层收发函数自带阻塞,你完全可以用最简单的程序结构,每个端口只用一个线程,发命令,阻塞收,处理,然后继续发。这样岀错概率更低。收发分离靠事件来互相通知的程序结构,确实是比较复杂的,如果不是非常需要高性能的场合,没必要这样做。can最就也就1兆bps,差不多100K字节每秒,阻塞式操作完全够。
页: [1]
查看完整版本: VS请教两个线程同时运行,如何保证两个线程内数据不丢包