小弟做一个软件,c#多线程的,一个主线程,处理用户的点击操作,一个辅助线程处理串口送来的数据,用户点击一个按钮,后我发送一些数据出去,下位机返回一些对应的数据,如果收到数据就把一个全局变量 byte 赋值为0x01;我在按钮的功能函数中睡眠一小会,确保数据已经发送完成,但是,遇到了奇怪的问题,明明数据发送来了,赋值操作已经在辅助线程中进行了,但是主线程中的依然是老数据(初始赋值0x03),不论你sleep多久。后来吧 前面加了修饰符 static,还有volatile,等,均无效;但是偶尔一次,我在主线程中加入了以messbox.show函数,发现数据成功更新,正常了,我晕倒了,这是什么情况,大侠给解释下,总不能总是给弹出对话框吧
send_data(send_buffer, 9);
Thread.Sleep(500);
while(_02==0x03 && count++ < 3)
{
Thread.Sleep(100);
}
MessageBox.Show("asd");//不加这两行就是老数据,加了就是新数据
MessageBox.Show("asd");
if (_02 == 0x01)
{
MessageBox.Show("ok");
break;
}
send_data(send_buffer, 9);
Thread.Sleep(500);
while(_02==0x03 && count++ < 3)
{
Thread.Sleep(100);
}
MessageBox.Show("asd");//不加这两行就是老数据,加了就是新数据
MessageBox.Show("asd");
if (_02 == 0x01)
{
MessageBox.Show("ok");
break;
}
因为设断点和MessageBox一样,让程序等一段时间才执行下面的代码
将thread.sleep(TIME)延长点时间试试
用lock
不要用静态变量或者 vloite。不可靠。
如果你不会找问题的话我给你出一个小招,你在更新数据的地方下个断点,断到之后看看堆栈,99.9%是在主线程中更新的。这个问题主要就是由于你不懂多线程造成的。另外,从你的帖子里可以看出,你对多线程可以说是一窍不通,建议你有时间可以补习补习。
而不是用一个信号变量和Sleep被动等待
小伙子,讨论问题要注意态度,态度不好,别人还愿意和你分享知识吗。虽然个别人言语不妥,但说得并非没有道理。虽然你用C#多年,但看你线程写成这样,俺也忍不住说一句:你的多线程技能需要提高。回到你的代码来看,业务俺不熟悉不多说,但只看sleep的调用,基本上可以判定你的线程实现是有问题的。也许今天运行没问题,哪天要求换个用法就会出错。俺审核别人的代码时,发现线程里有sleep的,一律要求改掉。即便是工作线程,也不可以随意使用sleep,这是写多线程的大忌。现在不懂没关系,也许哪天你就明白俺为什么这么说了。
sleep这东西,有时候还真不得不用
真的吗?WaitForXXXObject不可以代替sleep?你的代码要是给俺审核,凡是有sleep的,100%会被俺打回重写。
确实还没这么用过,能否给个简单的例子呢?
比如,通过C#进行Excel创建编辑操作后再打开这个Excel文件,在Excel保存和打开中使用sleep,确实我觉得用sleep实在是无赖的方式,如有实例麻烦发送邮件[email protected]
抱歉,没有C#代码可以给你参考,俺是搞C++的,C#不懂,不过道理相同。你说的exel打开编辑和保存,可以放在工作线程里去做,然后在主线程(也就是你的主窗口关联的线程)处理工作线程发送的自定义消息。假如工作线程叫A,在做完exel相关的任务之后,post一个消息给主窗口,主窗口收到这个消息后,弹出个对话框告诉用户exel处理完了。这样,主窗口就不会因为调用了sleep卡在那几秒钟,给用户的感觉好一些。不一定非要使用WaitForSinggleObject之类的函数,方法很多种,选适合项目要求的即可。
你的主要问题,应该是想知道什么时候操作完exel,而不是监视exel进程执行情况,对吧?office的2次开发俺接触过一些,关于word的,非exel。俺记得保存word,是有方法可以调用,是个阻塞函数。调用完了,保存也就完了,没那么复杂。exel应该也是如此,你查一下office2次开发相关资料吧。你的工作线程,如果是通过COM来操作exel,是可以知道什么时候操作完的。如果使用了一些非常规的办法操作exel,恐怕就没办法知道exel操作情况了。
你不会是写个独立的工作线程只做心跳检测功能吧?然后每sleep几秒就发送心跳包给服务器?奢侈啊。
能不用Thread尽量不用;
异步处理后,加个callback就perfect了;
这只是C#.net很早之前的版本,来后,都不使用该功能了;除非,根本不在乎准确性、稳定性;
能用异步函数则用;当年俺,使用COM口与下位机通讯,畅通无阻;
不对啊,你刚才问的不是心跳包么。心跳包,无论是TCP还是UDP,都要定时发送的。交互响应是和业务相关,和心跳包不一样,自然不需要定时发送。
呵呵,哥们,我也只是探讨学习啊,我的目的是你刚开始说的必须不能用Sleep,我就是想探讨某些方面的代码怎么写。
呵呵,不用Sleep的话,可以有很多替代的方式。Sleep在网络编程时最大的问题是会导致丢包,这个是不可接受的。如果是普通界面编程,可能会造成UI没响应或者响应缓慢,写得差的话,甚至会有死锁。所以俺审核代码时,有sleep的一律打回重写。
呵呵,出书了都,但愿你的书能帮到别人。实际的项目中,一般是不建议使用sleep的。原因是,一方面有潜在的死锁可能,另一方面会有响应时滞。尤其是项目大、模块多、业务流程繁琐的时候,一个小问题带来的影响会成倍放大,因此查找这个小个问题需要开发人员相互沟通,这都是开销。当然,不用sleep也会存在死锁的的可能,但比用sleep小得多。看你首帖代码,真不敢确定你对多线程很熟悉,不好意思,再次冒犯了。
sp1234是装 B大神 ,早就有人给盖棺定论了,这可不是我说的
说实在90%的sleep都是被乱用的,这些人都不了解自己在做什么,甚至为了停顿一下等原因在主线程中使用sleep,奇葩太多了。
相对于见到sleep语句,我更愿看到goto语句,编程书上说尽量不要使用goto语句,在我看来sleep倒是尽量不要使用的语句,原因就不解释了。
事实上能使用goto语句的人基本上水平要比这些随便使用sleep的人高很多。
我怎么没看清楚了,第一个,你说"我在按钮的功能函数中睡眠一小会,确保数据已经发送完成". 然后辅助线程中收到数据后对赋值,然后主线程中去判断的值嘛“,
我的意思也很简单,用户按下按钮,就将按钮disable,辅助线程收到数据后使用代理将按钮enable,根本不需要sleep操作,更何况你在主线程里面sleep,主界面调sleep时间稍长就会让用户感觉假死了。
第二个,你说了原因是“处理数据的线程我调用了主线程的一个控件,当时因为偷懒,设置为不检查跨线程调用问题,主线程睡眠,辅助线程被挂起,不小心害死猫”,于是我说“多线程时在线程中操作控件需要判断是否跨线程调用这是基本操作规范”,哪里没说到点子上了???
不敢苟同,找你这么说我们公司所有的自动化机器代码去不能合格
不设置线程sleep的话 就一直等待硬件响应的话 那是本末倒置
合格不合格,看公司怎么规定了,在俺这是不合格的。
线程等待事件发生,最好不使用sleep的最大原因不是不能实现功能,而是线程一旦sleep了,随机发生的事件无法及时被线程捕获。这样给客户的感觉是,你们的东西(硬件和软件)响应太慢了。另外,俺没搞明白你说的本末倒置啥意思。
2)全局变量,发消息让他来取
3)volatile