1000分~~~~~~~~~~~~~~~~~能解决要多少给多少!!!大家来讨论一下几个奇怪的问题,关于通讯和线程方面的(50分)

  • 主题发起人 主题发起人 lcl_003
  • 开始时间 开始时间
L

lcl_003

Unregistered / Unconfirmed
GUEST, unregistred user!
我是做工控软件的,现在遇到一个奇怪的问题,百思不得其解,以前到也能凑活用着,但是现在不行
了,所以想弄清楚到底是咋回事。
我的环境是用pc和另外一个工控方面用的pc104通讯,pc104 上用的是dos。我们之间是通过netbios会
话来进行通讯的。通讯部分用vc写在dll里了,下面是dll里发送和接收的原代码:
int APIENTRY SendData( int Lsn , char data[10000])
{
struct SessionMsg far *BufferPtrFar;
unsigned long i;
//out_buf.TextLength=4;
//out_buf.Text[0]=4;
//out_buf.Text[1]=0;
//out_buf.Text[2]=66;
//out_buf.Text[3]=1;

out_buf.TextLength=data[1]*256+data[0];
for(i=0;i<out_buf.TextLength;i++)
//{ vv.ww=data;
// out_buf.Text=vv.bb[0];
//}
out_buf.Text=data;
ClearNcb(&amp;SendNcb);
SendNcb.ncb_command=NCBRESET;
Netbios(&amp;SendNcb);
SendNcb.ncb_command = NCBSend;
SendNcb.ncb_lsn = (char)Lsn;
BufferPtrFar=(struct SessionMsg far *) &amp;out_buf;
SendNcb.ncb_buffer = (PUCHAR)(BufferPtrFar);
SendNcb.ncb_length = (int)out_buf.TextLength*2+4;
Netbios(&amp;SendNcb);
return data[0];//SendNcb.ncb_retcode ;
}

int APIENTRY RecvData(int Lsn, char *data)
{
struct SessionMsg far *BufferPtrFar;
unsigned long i;
// if( RecvNcb.ncb_retcode==0 ) {
// for(i=0;i<in_buf.TextLength;i++){
// data = in_buf.Text;
// }
ClearNcb(&amp;RecvNcb);
RecvNcb.ncb_command=NCBRESET;
Netbios(&amp;RecvNcb);
RecvNcb.ncb_command = 0x15;//NCBRECV;
RecvNcb.ncb_lsn = (char)Lsn;
BufferPtrFar=(struct SessionMsg far *) &amp;in_buf;
RecvNcb.ncb_buffer = (PUCHAR)(BufferPtrFar);
RecvNcb.ncb_length = sizeof(in_buf);
Netbios(&amp;RecvNcb);
if ( RecvNcb.ncb_retcode != 0 ) {
return RecvNcb.ncb_retcode ;

}
else
{
for(i=0;i<in_buf.TextLength;i++){
data = in_buf.Text;
}
return 0 ;
}
// }
// return 1;
}
我在delphi中使用是这么声明的:
function RecvData(lsn:integer;data:array of byte):integer;stdcall;external 'netdll.dll';
function SendData(lsn:integer;data:array of byte):integer;stdcall;external 'netdll.dll';
使用的时候直接调用就行了,比如:
setlength(send,5);
setlength(recv,24);
send[0]:=6;

send[1]:=0;
send[2]:=4;
send[3]:=2;
send[4]:=0;
SendData(lsn[1],send);
RecvData(lsn[1],recv);
下面问题出来了:我现在在一个线程里循环的和pc104通讯,不停的调用SendData、RecvData,但是
有的地方我必须将SendData、RecvData的返回值付给一个变量然后显示到edit里才可以,不然就报地
址错误。而且有的地方需要用有的就不需要用,我一遇到地址冲突的错误就这样:
i:=SendData(lsn[1],send);
main.edit1.text:=inttostr(i);
i:=RecvData(lsn[1],send);
main.edit1.text:=inttostr(i);
马上就没有错误了,屡试不爽:)而且不光是在线程里,在现成外也是这样。搞不清楚到底是怎么回
事。
另外还有个奇怪的问题,比如我在线程里使用了
i:=SendData(lsn[1],send);
main.edit1.text:=inttostr(i);
i:=RecvData(lsn[1],send);
main.edit1.text:=inttostr(i);
按理来说是访问了vcl应该是不安全的应该使用同步,但是我把main.edit1.text:=inttostr(i);写
在一个过程里然后使用同步,总是报地址错误。但是如果我直接写不用同步却一点问题没有,就是
跑一段时间后线程会死掉。我估计我线程死是不是和这个问题有关?我还有一个帖子是说线程
死掉的:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1630169
大家来分析一下这几个问题:
1,为什么有时候要把SendData的返回值显示到edit里才不出错?
2,线程里是用同步居然不行,而直接访问vcl:main.edit1.text:=inttostr(i);却可以?
3,线程为什么会死掉?
 
最好不要调用VCL内的一些属性,如果要调用的话
可以通过线程的特征值修改,比如发送字符串
property SendStr:string write SetSendStr;
发送的时候senddata(pointer(FSendStr)^);
 
我估计跟指针没有自动释放有些关系,我建议你将i设置为全局变量。另外应该使用同步。
 
爱元元的哥哥,
>>另外应该使用同步
可是我使用同步却报错啊,不使用同步却没问题:(
 
把变量赋给main.edit1.text才不会出错,为什么?
main.edit1.text可以自动管理,可以自己释放,为什么你不定义一个字符串,然后
var s:string;
i:=SendData(lsn[1],send);
s:=inttostr(i);
i:=RecvData(lsn[1],send);
s:=inttostr(i);
这样看看效果呢?我估计你只要赋给一个能够自动管理内存的变量都可以!
 
爱元元的哥哥, 如你所说,我赋给一个能够自动管理内存的变量的确是不报错了,但是线程
依然是运行一段时间后死掉了。不过好象比原来坚持的时间长了点:(
 
我怀疑你的vc代码有内存泄漏!
 
让线程执行慢下来(sleep),然后察看内存占用和Cpu占用(2000下可以直接看)!
 
内存泄露会有什么现象?但是平常用的时候没有问题啊
 
用数组来代替内存分配,这样速度慢一些,但是稳定性绝对没问题!
 
死机不就是占用资源过多!
 
爱元元的哥哥,我没有死机啊,只是线程死了。应用程序和系统没有死,还能响应。
张无忌,我现在就是用数组啊
任务管理器观察发现我的程序cpu时间很高,而且在增加,那到后来会不会出现系统死掉?
我的程序和system idle process的比较
pid cpu cpu时间 内存
我的程序 988 20 0:32 10M
system idle process 0 80 1:52 16K
 
你的程序里有一个地方不停的开内存,没有释放
 
setlength(send,5);
把这个代码换成一个固定的array[]就不用不停的分配内存了,规定一个字符串最大值
 
同意楼上的!
 
哦,我在线程刚开始的时候分配了一个动态数组
setlength(recv401,6000)
然后再循环,在循环里面我有用了几次setlength,但都没有开到6000那么长,和这个有关系?
setlength后必须要释放?
 
释放可以这样recv401:=nil;
 
啊!!!!用静态数组也不行:((
 
好东东,请看http://lui2008.8u8.com
 
后退
顶部