怪现象:线程中函数返回了没及时跳出函数

Allblus 2017-02-27 09:41:34
下图中的代码是在一个辅助线程的while循环中,朋友们帮忙分析分析啊,我们的非标自动化设备撞机了,分析日志文件发现这个怪现象。



...全文
599 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿领巾童鞋 2017-02-28
  • 打赏
  • 举报
回复
电脑不会骗人的,程序没有按预期走,肯定是有原因的,应该代码在你自己手中,只有靠你自己调了。当你自己解决问题后,才会涨见识。
Poopaye 2017-02-27
  • 打赏
  • 举报
回复
引用 6 楼 Allblus 的回复:
这段代码也是这样,不同的是,这段代码是放在UI线程的timer里面执行的。
像这种,不要怀疑c#什么有bug之类的,你应该考虑是最合理的逻辑。 第一次i=0,进来了然后返回 之后又调用了一次这个方法,但i=0时没有进来,i=1时进来了。 就是运行了2次
cpycpy000 2017-02-27
  • 打赏
  • 举报
回复
试试在两个判断false的中间加个sleep(100)
Allblus 2017-02-27
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
你这里,从所体现出的背后的基本的设计模式上,就存在着滥用线程while死循环的大问题,存在着不理解事件驱动设计的问题。
我的线程函数是如下代码这样的,通过变量来控制线程重入问题,同时由于线程访问了UI线程控件,加了Control.CheckForIllegalCrossThreadCalls = false; 不知道这样是否会导致Z轴没上升,程序就执行X轴移动命令,结果就是Z轴出现撞机现象! private void XY1AutoScrewThreadFun() { while (XY1ASThread) { if (GetCurrentWorkState() == 0) break; if (Y1IsEntry && !X2AST && !X1AST) { X1AST = true; if (StartY1Screw() == 0) { Y1Thread = false; Y2Thread = false; XY1ASThread = false; XY2ASThread = false; break; } X1AST = false; Y1ET = false; Y1IsEntry = false; } } }
xuggzu 2017-02-27
  • 打赏
  • 举报
回复
多线程调试方法要注意,否则你无法确定中断发生在哪个线程。
Allblus 2017-02-27
  • 打赏
  • 举报
回复
sp1234 大佬,我的线程函数是如下代码这样的,通过变量来控制线程重入问题,同时由于线程访问了UI线程控件,加了Control.CheckForIllegalCrossThreadCalls = false; 不知道这样是否会导致Z轴没上升,程序就执行X轴移动命令,结果就是Z轴出现撞机现象! private void XY1AutoScrewThreadFun() { while (XY1ASThread) { if (GetCurrentWorkState() == 0) break; if (Y1IsEntry && !X2AST && !X1AST) { X1AST = true; if (StartY1Screw() == 0) { Y1Thread = false; Y2Thread = false; XY1ASThread = false; XY2ASThread = false; break; } X1AST = false; Y1ET = false; Y1IsEntry = false; } } }
大鱼> 2017-02-27
  • 打赏
  • 举报
回复
引用 6 楼 Allblus 的回复:
这段代码也是这样,不同的是,这段代码是放在UI线程的timer里面执行的。
你难道不是已经return了吗?如果没有return应该执行Y1 螺丝钉1锁定完成。显然这句话是没有打印出来的。具体出现什么问题最好是单步调试进去。
  • 打赏
  • 举报
回复
从方法命名上看,你动不动就写 WaitxxxxxStop 的名字,我们把它还原为你心目中的系统时序图,就能看出来,你不是在设计一个事件驱动程序,而是在想当然地以为“函数输入输出”程序就能多线程并发操作。 虽然 c# 5 版本以后支持了 async/await 语法形式,但是它的实质也是需要了解其异步的本质,知道异步是“先执行调用 async 方法后边的代码,然后才回到 await 语句那里”去的。如果不理解这个,那么 async/await 语法就是有害的,让人误以为程序执行时序还是顺序的,而又平白无故地收到了异步执行的好处,产生了幻觉,丧失了调试能力。其实要想搞懂 async/await 编程机制,首先还是要先忘记这种这种企图,而先把异步、回调、事件驱动机制搞清楚,然后等感觉写回调事件代码比较繁琐时,才用 async/await 语法。 而你的代码应该是没有使用 async/await 机制,你用了更加诡异的“滥用一堆线程”方法来乱玩儿多线程编程。这就更缺少基础设计知识,没有得到警告,没有学过正确的多线程并发设计模式,错误地滥用了线程。
Allblus 2017-02-27
  • 打赏
  • 举报
回复
引用 4 楼 sp1234 的回复:
你这里,从所体现出的背后的基本的设计模式上,就存在着滥用线程while死循环的大问题,存在着不理解事件驱动设计的问题。
大侠讲这个,让我汗颜啊,难道我的程序要大改来避免这个事情。关键是撞机原因没找到。 有这方面的资料可以参考吗?
Allblus 2017-02-27
  • 打赏
  • 举报
回复
这段代码也是这样,不同的是,这段代码是放在UI线程的timer里面执行的。

Allblus 2017-02-27
  • 打赏
  • 举报
回复
引用 1 楼 Chinajiyong 的回复:
调试确定那个WaitSingle.....那个函数返回的false?、 仔细调试
确实是返回的false啊,你再看看,我把这段代码放在timer里面的,也发生过这样的事情。
  • 打赏
  • 举报
回复
你这里,从所体现出的背后的基本的设计模式上,就存在着滥用线程while死循环的大问题,存在着不理解事件驱动设计的问题。
  • 打赏
  • 举报
回复
既然你随便使用“线程”,随便while循环,那么通常你也就会随便解读“函数返回”概念。 当同一个方法有多个运行实例(多个线程)执行它时,你怎么注意你看到的 return false 语句是哪一个线程的呢?通常会忽视这一点,多线程的跟踪就是“跳来跳去”地在不同线程之间活动,因此通常根本不可能用肉眼去跟踪清楚多线程并发操作的流程。 这其实是一个大问题,不是你这里的代码能解释的。一个好的异步线程程序是不滥用线程的、不随便while循环的,每一个线程实际执行过程时间总是几毫秒、几十毫秒那样瞬间结束的。而你看到一个人动不动就说“用线程进行 while 循环、不断监控”的说法,基本上这个程序就丧失调试能力,乱猜流程。 这不仅仅是这里的问题,而是整个设计思路就是混沌的、错误地滥用线程的问题。再点用你这段代码的宿主代码中,就有问题,就过分地使用“死循环的线程”了。 以你这个段代码为例,假设当信息被改变了,通过其 NotifyPropertyChanged 接口模式,就可以事件通知“吸嘴真空报警”,干嘛要去死循环一个变量?既然这里弄个死循环,那么可想而知,调用这里的代码的宿主代码,就不得不用更多个、更滥的线程死循环来调用它。 不懂事件机制,滥用线程死循环,最后不仅仅丧失了系统CPU调度性能、额外多占大量内存,而且也丧失了调适能力。因为多线程跳来跳去本来是不能简单地认为“代码执行了 return false”的,你根本不清楚是哪一个线程执行的。
EnForGrass 2017-02-27
  • 打赏
  • 举报
回复
引用 1 楼 Chinajiyong 的回复:
调试确定那个WaitSingle.....那个函数返回的false?、 仔细调试
退出while循环,应该用break语句
EnForGrass 2017-02-27
  • 打赏
  • 举报
回复
调试确定那个WaitSingle.....那个函数返回的false?、 仔细调试
大然然 2017-02-27
  • 打赏
  • 举报
回复
会不会是因为多线程没有保证数据同步造成的? 比如改全局变量什么的? 如果真是这样,要加锁
sunny7862632 2017-02-27
  • 打赏
  • 举报
回复
说实话,这种贴半截代码的,根本看不出问题,最好办法就是单步调试
Allblus 2017-02-27
  • 打赏
  • 举报
回复
引用 14 楼 shingoscar 的回复:
[quote=引用 6 楼 Allblus 的回复:] 这段代码也是这样,不同的是,这段代码是放在UI线程的timer里面执行的。
像这种,不要怀疑c#什么有bug之类的,你应该考虑是最合理的逻辑。 第一次i=0,进来了然后返回 之后又调用了一次这个方法,但i=0时没有进来,i=1时进来了。 就是运行了2次[/quote] 要说又调用了一次这个方法,但在for循环前面我有一条Log记录,但是log文件里面这条记录没有打印出来,表示没有重复进来。
EnForGrass 2017-02-27
  • 打赏
  • 举报
回复
仔细检查你的代码逻辑吧,有问题
ystemni 2017-02-27
  • 打赏
  • 举报
回复
1、线程中涉及UI更新的,用委托让主线程处理 2、看样子是机械自动化,在多线程中操作机械,务必注意机械内部的BUFFER有没有冲突……
加载更多回复(1)

110,568

社区成员

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

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

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