C#多线程运行耗时的问题

penguin_1 2020-07-06 03:06:21
设计了一个数据采集系统,通过线程阻塞的方式,保证四个采集线程每次采集回来的数据都是同时的,在循环采集过程100次后,停止采集。但是在应用时候发现了一个问题,第一次点击button1,数据可以很好的采集并保存,第二次、第三次也都没有问题,但是,每次调试中,第四次采集数据时总会出现数据丢失的问题,就是正常情况下每个采集线程完成后应当保存有100个数据,但从第四次开始,数据一般只有80多个。之后,随着采集次数增多,数据缺失会越来越严重。(数据丢失的现象很稳定的出现在第四次)

我的代码贴在下面,求大佬们帮我看一眼,该怎么解决这个问题。


[DllImport("winmm")]
public static extern uint timeGetTime();
public static ManualResetEvent _mre = new ManualResetEvent(false);
private static Object thisLock = new object();

Thread th1;
Thread th2;
Thread th3;
Thread th4;
Thread th;

private void button1_Click(object sender, EventArgs e)//button1是开始按钮,单机开始采集数据
{
th1 = new Thread(getdata);
th1.Start();
th2 = new Thread(getdata);
th2.Start();
th3 = new Thread(getdata);
th3.Start();
th4 = new Thread(getdata);
th4.Start();

th = new Thread(timer);
th.Start();
}

void timer()
{
int t = 0;
int Millisecond = 100; //时钟触发间隔为100ms
while (t < 100) //定时器触发100次后自动结束
{
_mre.Reset();
uint timerstart = timeGetTime();
uint i = 0;
while (i < Millisecond)
{
i = timeGetTime() - timerstart;
}
timerstart = timeGetTime();
_mre.Set();
t = t + 1;
}
th1.Abort(); //销毁线程
th2.Abort(); //销毁线程
th3.Abort(); //销毁线程
th4.Abort(); //销毁线程
th.Abort(); //销毁线程
}

void getdata()
{
int nowtimes = 0;
while (nowtimes < 100)
{
Form1._mre.WaitOne();
lock (thisLock)
{
GetValue(); //从传感器获取数据
SaveValue(); //数据保存,将采集的数据保存到csv文本中
nowtimes = nowtimes + 1;
}
}
}
...全文
3334 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
yahle 2020-07-07
  • 打赏
  • 举报
回复
让我们来先捋一捋你的需求吧。 1. 你应该是外接了4台设备 2. 设备不能主动向服务器发起数据(推数据),只能服务器电脑去访问设备(拉数据) 3. 你打算间隔100ms,从这4台设备里分别读取他们的数据,并将这4个数据保存到一个独立的文件下。 限定条件有: 1. 4个设备需要获取同一时刻的数据,也就是说必须要保证在同一个时刻下同时获取数据 如果还有限定条件请补充,只有补充后,才好帮你重新设计代码结构。
八爻老骥 2020-07-07
  • 打赏
  • 举报
回复
异步获取,同步存储吗?传感器没有数据缓冲区吧,接收线程卡住了,数据不就白扔了,可以把采集到的数据先放一个同步队列里,再开一个线程一个取出来慢慢保存,这样就不会数据丢失了,除非程序中途异常退出。
  • 打赏
  • 举报
回复
新的异步编程开发的结构化语法,这是从“现代”的角度说的。回到了并发测试 GateValue 和 SaveValue 有没有在多线程运行时内部存储状态混乱冲突的问题,这是从测试来说的。如果先用几十个线程把核心过程测试过去了,然后再讨论主程序有没有混乱问题,这就好像是步子迈稳健了再跨楼梯。新语法是“术”,并发测试是“道”,二者相辅相成。你不习惯于道,各种术混乱使用,那么也可以通过学习现代的术来重新修道。
  • 打赏
  • 举报
回复
小程序,小功能,反而很繁琐很乱,堆砌了技术,这样就产生了因小失大的毛病。

任何一个貌似用于并发处理的过程,我们都应该拿几十个、上百个线程(或者Task)异步并发测试。注意是真正的异步并发,而不是用信号量、用异步的语法来做同步顺序阻塞的事情。这样就好像把一步步功能测稳定了,再来组合在一起。而组合的是时候就使用尽量简明清晰的思路,例如 #2 楼所写的
List<Task> tasks;
....
tasks.Add(Task.Run(()=>{
do1();
do2();
}));
结果[] temp= await Task.WhenAll(tasks);
这样的比较现代的更结构化的代码。当有编程设计效率高10倍的异步并发代码时,没有人喜欢研究诡异的信号量同步。
  • 打赏
  • 举报
回复
你同时并发 500个线程分别执行
                    GetValue();          //从传感器获取数据
SaveValue();
连续测试10次,你能每一次都准确的到500个结果吗?

实际上在粗糙的 GetValue 或者 SaveValue 内部就有冲突,结果是很混乱的。之所你问题好像还没有严重到完全不能用的地步,是因为你写的这个只有“4线程”的方法太简单了,有一点儿乱。大乱大治,小乱则是耗费时间。所以你认真地并发几十个、上百个线程去测试,以测试为准。不要只弄一个很简单的程序,然后解决不了技术设计问题。
圣殿骑士18 2020-07-07
  • 打赏
  • 举报
回复
你这个设计有问题,采集的数据是怎么来的?是不是发送方提供的?如果发送方提供的数据不是准时的,你怎么保证你采集的数据是准确的? 所以你这个设计就有问题,你要求:1)发送方没问题,2)采集方没问题。这是一种强耦合。 你从设计上,应该解耦。 首先准不准时发,那是发送方的问题。其次,你只要保证每一个采集点,都能采集到数据。然后,时间是不是一致,你记录下采集时间,也可以作为后验证。 在这种设计下,发送=》采集,可以处理为一个事件机制。
libolei 2020-07-06
  • 打赏
  • 举报
回复
GetValue(); SaveValue(); 这两行代码里是不是报异常了
libolei 2020-07-06
  • 打赏
  • 举报
回复
Form1._mre.WaitOne(); 这行代码是什么逻辑
wanghui0380 2020-07-06
  • 打赏
  • 举报
回复
task<结果> 采集数据1() { task.yield() } task<结果> 采集数据2() {task.yield() } 结合你上一个帖子,这里可以放上task.yield,告诉cpu我先掠过,下一轮在说。这样可以保证你多task能尽量快速进入准备状态。那么就可能被同时被系统快速分配。同时task调度器可以使用让他尽可能被公平调度
wanghui0380 2020-07-06
  • 打赏
  • 举报
回复
看不出你这个代码,从哪里能得出,每次必定为100个任何保证。 就是你说的前3次,其实依旧是“巧合”,碰巧cpu在100*100ms左右把100个任务完成了 貌似好像你这个描述,你这个处理要求,我好像有些印象。嗯,看了一下你以前的帖子,果然还是那个问题。 那个帖子已经提醒你了,线程会堆叠。如果前面的不走,后面继续加,最终是肯定是这结果。 按照你目前的描述,伪代码
slim=slim(3) //下异步锁,并限制最大次数

 采集调度()
{
   CancelToken //这个我们不清楚你环境,需不要需要设置超时,强制退出,就自己看着办了
     
   await  slim.asynwait();  //异步锁,保证你前面有3个在运行,后面一个先等着
    
    for(i t0 100)
 {
    结果[]  temp=  await  Task.WhenAll(采集数据1,采集数据2) //他们可以异步并行
  }
 
 //这里100次并行采集结束。至于保存其实可以延后。所以这里另外启动一个save task。或者干脆直接用TaskCompletionSource丢给外面,让外面自己决定怎么处理他
    slim.释放();
 }

  task<结果> 采集数据1()
{
}

  task<结果> 采集数据2()
{
}
threenewbee 2020-07-06
  • 打赏
  • 举报
回复
线程阻塞,那就等于单线程
GetValue(); //从传感器获取数据
SaveValue();
这些都在锁里面呢

110,536

社区成员

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

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

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