c# 多线程使用多年,今天算是栽了,高手请进

renfei0730 2013-01-21 06:22:12
小弟做一个软件,c#多线程的,一个主线程,处理用户的点击操作,一个辅助线程处理串口送来的数据,用户点击一个按钮,后我发送一些数据出去,下位机返回一些对应的数据,如果收到数据就把一个全局变量 byte mark赋值为0x01;我在按钮的功能函数中睡眠一小会,确保数据已经发送完成,但是,遇到了奇怪的问题,明明数据发送来了,mark赋值操作已经在辅助线程中进行了,但是主线程中的mark依然是老数据(初始赋值0x03),不论你sleep多久。后来吧mark 前面加了修饰符 static,还有volatile,等,均无效;但是偶尔一次,我在主线程中加入了以messbox.show函数,发现数据成功更新,正常了,我晕倒了,这是什么情况,大侠给解释下,总不能总是给弹出对话框吧
send_data(send_buffer, 9);
Thread.Sleep(500);
while(mark_02==0x03 && count++ < 3)
{
Thread.Sleep(100);
}
MessageBox.Show("asd");//不加这两行就是老数据,加了就是新数据
MessageBox.Show("asd");
if (mark_02 == 0x01)
{
MessageBox.Show("ok");
break;
}
...全文
7855 98 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
98 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-03-05
  • 打赏
  • 举报
回复
1)发消息让他来取 2)全局变量,发消息让他来取 3)volatile
newlovedew 2013-02-28
  • 打赏
  • 举报
回复
好贴!!!!!!!
边走边瞧 2013-02-25
  • 打赏
  • 举报
回复
引用 95 楼 meskin0556 的回复:
不敢苟同,找你这么说我们公司所有的自动化机器代码去不能合格 不设置线程sleep的话 就一直等待硬件响应的话 那是本末倒置
合格不合格,看公司怎么规定了,在俺这是不合格的。 线程等待事件发生,最好不使用sleep的最大原因不是不能实现功能,而是线程一旦sleep了,随机发生的事件无法及时被线程捕获。这样给客户的感觉是,你们的东西(硬件和软件)响应太慢了。 另外,俺没搞明白你说的本末倒置啥意思。
meskin0556 2013-02-25
  • 打赏
  • 举报
回复
引用 45 楼 go_and_see 的回复:
引用 26 楼 renfei0730 的回复:问题已经解决,需要知道的,留言 小伙子,讨论问题要注意态度,态度不好,别人还愿意和你分享知识吗。虽然个别人言语不妥,但说得并非没有道理。虽然你用C#多年,但看你线程写成这样,俺也忍不住说一句:你的多线程技能需要提高。 回到你的代码来看,业务俺不熟悉不多说,但只看sleep的调用,基本上可以判定你的线程实现是有问题的……
不敢苟同,找你这么说我们公司所有的自动化机器代码去不能合格 不设置线程sleep的话 就一直等待硬件响应的话 那是本末倒置
renfei0730 2013-01-28
  • 打赏
  • 举报
回复
引用 90 楼 zipper9527 的回复:
引用 88 楼 renfei0730 的回复:我对大家不看清楚问题就来回答的习惯,很是无语,这都是那里和那里? 引用 87 楼 zipper9527 的回复:靠sleep多不靠谱啊,发消息时候就disable掉按钮,收到数据时将按钮enable,还sleep个啥。多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范 引用 86 楼 smace 的回复……
是这样的,按下按键已经disable了按钮,你知道iso1443a的卡有个情况,就是连续读写会失败,这个是卡标准里面规定好的,数值很关键,仅仅操作一次那么有50%以上的几率读写卡失败(卡本身特性),严重影响用户体验,并且写入成功或者失败需要弹框提示用户,所以我需要分析返回数据(10多个byte)来判断是否再次尝试写入操作,如果是加减值操作,则决不允许重复进行,所以仅仅disable enable 是不够的,最多0.3s的睡眠,期间就是不响应用户输入,时间很短,基本感觉不到。。大家讨论而已,
zipper9527 2013-01-28
  • 打赏
  • 举报
回复
引用 88 楼 renfei0730 的回复:
我对大家不看清楚问题就来回答的习惯,很是无语,这都是那里和那里? 引用 87 楼 zipper9527 的回复:靠sleep多不靠谱啊,发消息时候就disable掉按钮,收到数据时将按钮enable,还sleep个啥。多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范 引用 86 楼 smace 的回复:多线程不是那么用的,睡眠一小会不能保证数据全……
我怎么没看清楚了,第一个,你说"我在按钮的功能函数中睡眠一小会,确保数据已经发送完成". 然后辅助线程中收到数据后对mark赋值,然后主线程中去判断mark的值嘛“, 我的意思也很简单,用户按下按钮,就将按钮disable,辅助线程收到数据后使用代理将按钮enable,根本不需要sleep操作,更何况你在主线程里面sleep,主界面调sleep时间稍长就会让用户感觉假死了。 第二个,你说了原因是“处理数据的线程我调用了主线程的一个控件,当时因为偷懒,设置为不检查跨线程调用问题,主线程睡眠,辅助线程被挂起,不小心害死猫”,于是我说“多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范”,哪里没说到点子上了???
dreamgis 2013-01-28
  • 打赏
  • 举报
回复
多线程算是一个难点,,未完全吃透的飘过
Delta 2013-01-28
  • 打赏
  • 举报
回复
来看看。如何?顺便学习一下了。
hz_gis 2013-01-28
  • 打赏
  • 举报
回复
一个错误的开始导致了更多的错误...
yanmaicao2004 2013-01-27
  • 打赏
  • 举报
回复
很明显,你的这段程序的思路有问题,应该采用异步回调或事件来触发后续工作,你这么处理太无理了。
renfei0730 2013-01-27
  • 打赏
  • 举报
回复
我对大家不看清楚问题就来回答的习惯,很是无语,这都是那里和那里?
引用 87 楼 zipper9527 的回复:
靠sleep多不靠谱啊,发消息时候就disable掉按钮,收到数据时将按钮enable,还sleep个啥。多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范
引用 86 楼 smace 的回复:
多线程不是那么用的,睡眠一小会不能保证数据全部发送完了,有可能发送完也可能没发送完,应该加互斥锁,确保在处理发送数据的时候已经发送完了,才让主线程执行下去
我对大家不看清楚问题就来回答的习惯,很是无语,这都是那里和那里?我们说的不是一个事情
zipper9527 2013-01-27
  • 打赏
  • 举报
回复
靠sleep多不靠谱啊,发消息时候就disable掉按钮,收到数据时将按钮enable,还sleep个啥。多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范
smace 2013-01-26
  • 打赏
  • 举报
回复
多线程不是那么用的,睡眠一小会不能保证数据全部发送完了,有可能发送完也可能没发送完,应该加互斥锁,确保在处理发送数据的时候已经发送完了,才让主线程执行下去
DSIOF3KIDSKTR 2013-01-26
  • 打赏
  • 举报
回复
引用 45 楼 go_and_see 的回复:
引用 26 楼 renfei0730 的回复:问题已经解决,需要知道的,留言 小伙子,讨论问题要注意态度,态度不好,别人还愿意和你分享知识吗。虽然个别人言语不妥,但说得并非没有道理。虽然你用C#多年,但看你线程写成这样,俺也忍不住说一句:你的多线程技能需要提高。 回到你的代码来看,业务俺不熟悉不多说,但只看sleep的调用,基本上可以判定你的线程实现是有问题的……
同感啊,非常厌恶看到别人胡乱使用sleep。 说实在90%的sleep都是被乱用的,这些人都不了解自己在做什么,甚至为了停顿一下等原因在主线程中使用sleep,奇葩太多了。 相对于见到sleep语句,我更愿看到goto语句,编程书上说尽量不要使用goto语句,在我看来sleep倒是尽量不要使用的语句,原因就不解释了。 事实上能使用goto语句的人基本上水平要比这些随便使用sleep的人高很多。
莫聆 2013-01-26
  • 打赏
  • 举报
回复
虽然c#线程使用了很多年,但知识看来很狭窄。这个while循环完之后判断mark==0x01之前也的加上sleep,不过这不是个好实践,最好的方法还是用事件量来等待。
renfei0730 2013-01-25
  • 打赏
  • 举报
回复
引用 81 楼 linustd 的回复:
第一次看到依靠Thread.Sleep来等待数据发送的. 从socket读取数据是一个阻塞方法, 每次把读取到的数据缓存起来就行. Thread.Sleep挂起线程后, 有可能造成其它线程也无法修改数据.或者说 线程唤醒后, 读取的不是本来的数据. Messagebox.Show也会暂停当前线程的执行, 但是人家微软不是用sleep阻塞当前线程的, 人家……
你仔细看看吧
普世编程技术 2013-01-25
  • 打赏
  • 举报
回复
第一次看到依靠Thread.Sleep来等待数据发送的. 从socket读取数据是一个阻塞方法, 每次把读取到的数据缓存起来就行. Thread.Sleep挂起线程后, 有可能造成其它线程也无法修改数据.或者说 线程唤醒后, 读取的不是本来的数据. Messagebox.Show也会暂停当前线程的执行, 但是人家微软不是用sleep阻塞当前线程的, 人家用的是合理的方法, 所以你Messagebox.Show之后, 收到了数据. 总之, 别依靠瞎蒙来编程, 现在很多人真是无知者无畏.
yazhouren 2013-01-25
  • 打赏
  • 举报
回复
多线程编程基础不扎实
liujiang917 2013-01-25
  • 打赏
  • 举报
回复
用BackGroundWork吧,比直接用线程好多了
裸奔在上海 2013-01-24
  • 打赏
  • 举报
回复
楼主写那么多,还不如写个异步委托处理一下。你接收值的方法也没有贴出来,这个有点难下结论为何不行了
加载更多回复(78)

111,097

社区成员

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

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

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