serialport串口通讯出现“由于线程退出或应用程序请求,已放弃I/O操作”的错误 本帖最后由 zy_6084 于 2013-07-17 09:36:53 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 没做过WPF的,根据楼主的描述,会不会是点下按钮的时候,正好在读取串口了,但是被强制终止,所以才发生此错误?楼主看下错误发生的地方以及Exception的类型,看下该异常的解释 感谢楼上的解答。我的错误一般发生在我定义的事件接收标志位上。一般主画面上一到读取这个值做逻辑判断,就死到那了,连错误都不报。那我能不能加个当写入按钮触发时,如果正在接收数据,这时等待一段时间。等到接收事件完成后(此处再用一个接收事件完成的标志位),再写入数据?还是我直接把接收事件用LOCK语句包起来,这样是否也能达到类似效果? 部分代码如下,全部代码比较长//接受串口数据 public void myserialport_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { receiving = true; //接收事件标志位 readData = new byte[myserialport.BytesToRead]; myserialport.Read(readData, 0, readData.Length); myserialport.DiscardOutBuffer(); string tempstr; tempstr = Convert.ToString(readData[0], 16); switch (funcode)//更改接收事件触发的阀值 { case "读取": myserialport.ReceivedBytesThreshold = 28; break; case "写入": myserialport.ReceivedBytesThreshold = 24; break; case "停止": myserialport.ReceivedBytesThreshold = 22; break; case "运行": myserialport.ReceivedBytesThreshold = 22; break; } if (tempstr.ToUpper() == "E5")//PLC第一次返回数值正确,PC再次发送命令给PLC { byte[] arrayResend1 = new byte[6]; arrayResend1[0] = 0x10; arrayResend1[1] = 0x02; arrayResend1[2] = 0x00; arrayResend1[3] = 0x5C; arrayResend1[4] = 0x5E; arrayResend1[5] = 0x16; Thread.Sleep(50); myserialport.Write(arrayResend1, 0, 6); } else if (tempstr.ToUpper() != "")//如果PC第一次发给PLC值正确,PLC第一次返回必为E5,然后再次发送命令,此时PLC二次返回必不会是E5,所以此时触发显示事件 { receiving=false; OnDisplay(new EventArgs());//自定义的主界面显示事件触发方法 } } //catch (Exception err) //{ // errcode=err.Message; // OnChilderror(new EventArgs()); //} catch (Exception err) { errcode=err.Message; } }//写入按钮事件 private void btnstart_Click(object sender, RoutedEventArgs e) { try { timer.Stop();//停止计时器 txtpos.Text = ""; txtdis1.Text = ""; while (writeflag == true)//写入数据方法的标志位 { if (ppidll.Receiving == false) { if (word1 && word2)//判断两次写入成功的标志 { writeflag = false; word1 = false; word2 = false; } if (ppidll.Flag1 == false && ppidll.Sign3 == true) { ppidll.WritePPIWord("04", "01", "01", "84", "000096", "10", "1000"); } if (ppidll.Flag1 == false && ppidll.Sign4 == true) { ppidll.WritePPIWord("04", "01", "01", "84", "000160", "10", "5000"); } } if (ppidll.Receiving == true) { ppidll.Receiving = false; } } } catch (ThreadAbortException) { timer.Start(); } } 1.界面卡死最终本质原因是 widnows消息得不到及时处理2.发生1的原因有两个: 1)UI线程阻塞,可能是你程序写得有问题,比如执行耗时操作,也可能UI线程和其他子线程发生死锁 2)子线程占用CPU控制权太频繁,造成UI线程得不到足够CPU时间片,也就是UI线程经常被挂起3.贴代码 看得清楚 不然没人懂 就像上面1、2感觉不接地气 数据接收和写入没必要分开 可以同时进行 不知道你timer干啥用while (writeflag == true)//写入数据方法的标志位这个条件有可能一直未true吗 如果是 界面卡死必然 我写定时器因为需要实时读取PLC中的部分值做显示。wirteflag在PLC二次返回数据时执行界面更新时变为FALSE,再次执行写入方法时TRUE 请问各位大哥,一般笔试答对几成可以进入下一轮. 论文列表是什么做的? Invalidate() 问题 关于C#中配置web service的问题 C#中怎样copy目录? "未将对象引用设置到对象的实例"问题,请帮忙,谢谢~~~ 大家感觉《。net框架程序设计(修订版)》怎样? 能不能够让datagrid的头两列固定住,不跟随水平滚动条的滚动而滚动 c#中的maskedtextbox取值问题 csdn 网站怎么这么慢啊! 关于web。config文件中添加内容问题 WCF
//接受串口数据
public void myserialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
receiving = true; //接收事件标志位
readData = new byte[myserialport.BytesToRead];
myserialport.Read(readData, 0, readData.Length);
myserialport.DiscardOutBuffer();
string tempstr;
tempstr = Convert.ToString(readData[0], 16);
switch (funcode)//更改接收事件触发的阀值
{
case "读取":
myserialport.ReceivedBytesThreshold = 28;
break;
case "写入":
myserialport.ReceivedBytesThreshold = 24;
break;
case "停止":
myserialport.ReceivedBytesThreshold = 22;
break;
case "运行":
myserialport.ReceivedBytesThreshold = 22;
break;
}
if (tempstr.ToUpper() == "E5")//PLC第一次返回数值正确,PC再次发送命令给PLC
{
byte[] arrayResend1 = new byte[6];
arrayResend1[0] = 0x10;
arrayResend1[1] = 0x02;
arrayResend1[2] = 0x00;
arrayResend1[3] = 0x5C;
arrayResend1[4] = 0x5E;
arrayResend1[5] = 0x16;
Thread.Sleep(50);
myserialport.Write(arrayResend1, 0, 6);
}
else if (tempstr.ToUpper() != "")//如果PC第一次发给PLC值正确,PLC第一次返回必为E5,然后再次发送命令,此时PLC二次返回必不会是E5,所以此时触发显示事件
{
receiving=false;
OnDisplay(new EventArgs());//自定义的主界面显示事件触发方法
}
}
//catch (Exception err)
//{
// errcode=err.Message;
// OnChilderror(new EventArgs());
//}
catch (Exception err)
{
errcode=err.Message;
}
}
//写入按钮事件
private void btnstart_Click(object sender, RoutedEventArgs e)
{
try
{
timer.Stop();//停止计时器
txtpos.Text = "";
txtdis1.Text = "";
while (writeflag == true)//写入数据方法的标志位
{
if (ppidll.Receiving == false)
{ if (word1 && word2)//判断两次写入成功的标志
{
writeflag = false;
word1 = false;
word2 = false;
}
if (ppidll.Flag1 == false && ppidll.Sign3 == true)
{
ppidll.WritePPIWord("04", "01", "01", "84", "000096", "10", "1000");
} if (ppidll.Flag1 == false && ppidll.Sign4 == true)
{
ppidll.WritePPIWord("04", "01", "01", "84", "000160", "10", "5000");
} }
if (ppidll.Receiving == true)
{
ppidll.Receiving = false;
}
}
}
catch (ThreadAbortException)
{
timer.Start();
}
}
2.发生1的原因有两个:
1)UI线程阻塞,可能是你程序写得有问题,比如执行耗时操作,也可能UI线程和其他子线程发生死锁
2)子线程占用CPU控制权太频繁,造成UI线程得不到足够CPU时间片,也就是UI线程经常被挂起
3.贴代码 看得清楚 不然没人懂 就像上面1、2感觉不接地气
while (writeflag == true)//写入数据方法的标志位
这个条件有可能一直未true吗 如果是 界面卡死必然