线程无故退出

wjx_0_2001 2009-12-29 04:34:35
背景:一个程序(基于DLG)通过调用第三方提供的接口,进行读卡


附注:这个程序时通过两个COM口,来读卡的,两个COM口是轮换着读卡(不管当前有没有在读卡或者出现异常)


问题:在这个程序启动后,有时候不读卡,但是,程序时通过一个线程,循环(死循环)读卡的,如果读到卡,就在DLG界面

上显示

==============================================================================================================
实在找不问题在哪儿,只好在程序中加入日志,希望能通过日志发现问题

流程如下:

void lpRecvProc(LPVOID lpParam)
{
// 取得窗口指针
CMyCardDlg* pDlg=(CMyCardDlg*)lpParam;

// 初始化接口

// 初始化刷卡机端口
long ret = iniCom( pDlg->m_nCom);
long ret2=iniCom(pDlg->m_nCom2);

if(ret != 0||ret2!=0)
{
AfxMessageBox("端口初始化失败!");
return ;
}


bool bIsBusy=false;//false 表示当前没有处理卡信息,true 表示正在处理卡信息

bool bIsflag=false;//false 表示通过COM1口读卡,true 表示通过COM2口读卡


// 开始循环读卡
while(true)
{
if(bIsBusy==true)
{
WriteLog(正在处理卡信息);
continue;
}

// 取得用户卡信息
//if(bIsflag==false)
{
::WriteLog(com1读卡前);//表示当前用com1读卡,但是还没读 //
ret = readCard(com1,...)//通过接口读卡
//
::WriteLog(com1读卡后);//表示当前用com1读卡,已经读完卡
//
}
else
{
::WriteLog(com2读卡前);//表示当前用com2读卡,但是还没读 //
ret = readCard(com2,...)//通过接口读卡
//
::WriteLog(com2读卡后);//表示当前用com2读卡,已经读完卡

}

bIsBusy = true;

switch( ret)
{
case 0:// 成功
break;
case 1:// 无卡
case 2://
default:// 异常返回值
bIsBusy=false;
bIsflag=!bIsflag;
WriteLog(无卡);//
continue;
}

pDlg->SendMessage( WM_USER+2 );数据打包,请求服务处理

数据解析,将服务处理的结果值赋予ret

switch ( ret )
{
case 0:
显示刷卡成功
break;
case 1:
显示扣款成功
break;
default:
显示操作失败
break;
}

bIsBusy=false;
bIsflag=!bIsflag;
continue;

}
WriteLog(线程退出);
return;

}

==========================================
有点多,呵


再次出现这个问题时,程序执行到标记为红处后,就停止了,因为这个时候日志没有变化了


既在WriteLog(com1读卡前);//或者WriteLog(com2读卡前);//执行后,


线程就没有在循环工作了


-----------------------------
但这个是死循环,没有理由退出

望各位给给意见

多谢先了

...全文
531 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
呵呵

其实只要看我最开始贴的就行,那我简约点贴
void lpRecvProc(LPVOID lpParam)
{
// 取得窗口指针
CMyCardDlg* pDlg=(CMyCardDlg*)lpParam;

// 初始化接口

// 初始化刷卡机端口
long ret = iniCom( pDlg->m_nCom);
long ret2=iniCom(pDlg->m_nCom2);

if(ret != 0||ret2!=0)
{
AfxMessageBox("端口初始化失败!");
return ;
}


bool bIsBusy=false;//false 表示当前没有处理卡信息,true 表示正在处理卡信息

bool bIsflag=false;//false 表示通过COM1口读卡,true 表示通过COM2口读卡


// 开始循环读卡
while(true)
{
if(bIsBusy==true)
{
WriteLog(正在处理卡信息);
continue;
}
try
{
// 取得用户卡信息
if(bIsflag==false)
{
::WriteLog(com1读卡前);//表示当前用com1读卡,但是还没读 //
ret = readCard(com1,...)//通过接口读卡
::WriteLog(com1读卡后);//表示当前用com1读卡,已经读完卡

}
else
{
::WriteLog(com2读卡前);//表示当前用com2读卡,但是还没读 //
ret = readCard(com2,...)//通过接口读卡
::WriteLog(com2读卡后);//表示当前用com2读卡,已经读完卡

}
}
catch(...)
{
::WriteLog(异常);//
}

bIsBusy = true;

switch( ret)
{
case 0:// 成功
break;
case 1:// 无卡
case 2://
default:// 异常返回值
bIsBusy=false;
bIsflag=!bIsflag;
WriteLog(无卡);//
continue;
}
…………
///

附注:
红色标记的,为执行这行代码后,就不在往下执行了,WriteLog是后来加上的,所以,肯定不会是这个出问题

lllyyy2403 2010-01-11
  • 打赏
  • 举报
回复
兄弟,这代码也太长了点哈,建议先用MessageBox查查情况,然后针对一小段代码提问效果会更好。
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
没贴好
luan
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
void lpRecvProc(LPVOID lpParam)
{
// 取得窗口指针
CMyCardDlg* pDlg=(CMyCardDlg*)lpParam;

// 初始化接口
HINSTANCE mlib;
IniCom iniCom;
CloseCom closeCom;
ReadCard readCard;
DecCard decCard;

int Money;//单位分
mlib = LoadLibrary("connectv23.dll");



if(mlib != NULL)
{
iniCom = (IniCom)GetProcAddress(mlib , "Connect");
closeCom = (CloseCom)GetProcAddress(mlib , "Disconnect");
readCard = (ReadCard)GetProcAddress(mlib , "ReadCardInfo");
decCard = (DecCard)GetProcAddress(mlib , "DecCardMoney");
}
else
{
AfxMessageBox("加载动态库失败,请重新启动程序!");
return;
}

if(iniCom==NULL||closeCom==NULL||readCard==NULL||decCard==NULL)
{
AfxMessageBox("加载动态库失败,请重新启动程序!");
return;
}

// 初始化刷卡机端口
long ret = iniCom( pDlg->m_nCom);
long ret2=iniCom(pDlg->m_nCom2);

if(ret != 0||ret2!=0)
{
AfxMessageBox("端口初始化失败!");
return ;
}

CString strcardno;
int npos=-1;

CString strError="";

CString strLog="";//

//unsigned char ucShowCardNo[256],ucName[256],ucCardNo[256],ucMoney[256];
//unsigned char ucDeCardNo[3];

bool bIsBusy=false;

bool bIsflag=false;

CTime time

DWORD dwError;

// 开始循环读卡
while(true)
{

unsigned char ucShowCardNo[256],ucName[256],ucCardNo[256],ucMoney[256];
unsigned char ucDeCardNo[3];
memset(ucShowCardNo,0x00,sizeof(ucShowCardNo));
memset(ucCardNo,0x00,sizeof(ucCardNo));
memset(ucName,0x00,sizeof(ucName));
memset(ucMoney,0x00,sizeof(ucMoney));

pDlg->m_FlagBmp.DeleteObject();

try
{ // 取得用户卡信息
if(bIsflag==false)
{

::WriteLog("com1前");//每次在这里执行完后,就停止了,可能执行了,但导致异常


ret = readCard(pDlg->m_nCom,
ucShowCardNo
ucName,
ucCardNo,
ucMoney
);
::WriteLog("com1后");
}
else
{
::WriteLog("com2前");//每次在这里执行完后停止了,后面就不在执行,可能执行了,但导致异常

ret = readCard(pDlg->m_nCom2,
ucShowCardNo,
ucName,
ucCardNo,
ucMoney
);
::WriteLog("com2后");
}
}
catch(...)
{
::WriteLog("线程异常");
}


bIsBusy = true;

switch( ret)
{
case 0:// 成功
break;
case 1:// 无卡

pDlg->m_usrstatus.Format("无卡!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR);
pDlg->m_sBitmap.SetBitmap(pDlg->m_FlagBmp);
pDlg->SendMessage( WM_USER+1);//更新显示
bIsBusy=false;
bIsflag=!bIsflag;
::WriteLog("无卡");
Sleep(100);
continue;
case 2:// 非系统发行卡
pDlg->m_usrstatus.Format("非系统发行卡!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 3://挂失卡
pDlg->m_usrstatus.Format("挂失卡!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 4:// 已过有效期
pDlg->m_usrstatus.Format("该卡已过有效期!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 5://卡类使用不允许
pDlg->m_usrstatus.Format("卡类使用不允许!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 6://感应头通信失败
pDlg->m_usrstatus.Format("感应头通信失败!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 8://中途拔卡
pDlg->m_usrstatus.Format("中途拔卡!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case 9://金额不足
pDlg->m_usrstatus.Format("金额不足!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
case -6://与POS通信超时
pDlg->m_usrstatus.Format("通信超时!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
continue;
default:// 异常返回值
pDlg->m_usrstatus.Format("接口读卡异常!");//1210
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
pDlg->SendMessage( WM_USER+1 );
Sleep(pDlg->m_lRTime);
bIsBusy=false;
bIsflag=!bIsflag;
WriteLog("接口异常");//
continue;
}
//
npos=-1;//
strcardno="";
strcardno=ucShowCardNo;
npos=strcardno.Find(" ");
strcardno=strcardno.Left(npos);
pDlg->m_cardID =strcardno ;
pDlg->m_cardID.TrimLeft();
pDlg->m_cardID.TrimRight();

Money=::GetIntMoney(ucMoney);//money);

// 数据打包

pDlg->m_pPack = (PACKAGE*)pDlg->m_buf;
memset(pDlg->m_pPack->number , 0 , 80);
memset(pDlg->m_pPack->returnInfo , 0 ,80);
memset(pDlg->m_pPack->groupName , 0 , 80);
memset(pDlg->m_pPack->loginName , 0 , 80);
memset(pDlg->m_pPack->userName , 0 , 80);
pDlg->m_pPack->type =2;
strcpy(pDlg->m_pPack->number, pDlg->m_cardID) ;
pDlg->m_pPack->roomid = pDlg->m_nID;
pDlg->m_pPack->money = Money;

// 请求服务处理
pDlg->SendMessage( WM_USER+2 );//服务处理

CString strBalance;
CString test ="wrong!";
int leftMoney =0;//
leftMoney= pDlg->m_pPack->money;//
ret = pDlg->m_pPack->type;
int cost=0;
cost = Money - leftMoney;

switch ( ret )
{
case 0:
pDlg->m_usrstatus="读卡成功";
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_UP);
pDlg->m_sBitmap.SetBitmap(pDlg->m_FlagBmp);
break;
case 1:
pDlg->m_usrstatus="扣款成功";
// 扣款
if(cost>0.00)
{
memset(ucDeCardNo,0x00,sizeof(ucDeCardNo));
ucDeCardNo[0] = ucCardNo[0];
ucDeCardNo[1] = ucCardNo[1];
ucDeCardNo[2] = ucCardNo[2];

if(bIsflag==false)
{
ret = decCard(pDlg->m_nCom , ucDeCardNo , cost );
}
else
{
ret = decCard(pDlg->m_nCom2 , ucDeCardNo , cost );//cardID
}
}
else
{
ret=0;
}


if( ret == 0 )
{
// 扣款成功
pDlg->m_pPack->type = 20; //
pDlg->m_pPack->money = Money;//;
pDlg->SendMessage( WM_USER+2);
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_DOWN );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );

WriteLog("扣款成功");//

}
else if(ret==9)
{
pDlg->m_usrstatus.Format("金额不足!");
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
WriteLog("金额不足");//
}
else
{
pDlg->m_usrstatus.Format("失败 %d:%d" , ret , leftMoney);
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
WriteLog("失败");//
}
break;
default:
pDlg->m_usrstatus="操作失败";
pDlg->m_FlagBmp.LoadBitmap(IDB_BITMAP_ERROR );
pDlg->m_sBitmap.SetBitmap( pDlg->m_FlagBmp );
WriteLog("操作失败");
break;
}

pDlg->m_strLoginName = pDlg->m_pPack->loginName;
pDlg->m_strUserName= pDlg->m_pPack->userName;
pDlg->m_money=pDlg->m_pPack->returnInfo;
pDlg->m_money += strBalance;
pDlg->m_classname = pDlg->m_pPack->groupName ;

pDlg->m_cardID = "";
pDlg->SendMessage( WM_USER+1);
Sleep(1000);

pDlg->m_strLoginName ="";
pDlg->m_strUserName="";
pDlg->m_money="";
pDlg->m_money += strBalance;
pDlg->m_classname ="" ;

pDlg->m_cardID = "";
pDlg->SendMessage( WM_USER+1);
//pDlg->m_bBusy = FALSE;
bIsBusy=false;
bIsflag=!bIsflag;
continue;//

}
closeCom(pDlg->m_nCom);
closeCom(pDlg->m_nCom2);
FreeLibrary(mlib);
return;

}
zhangrenhui 2010-01-11
  • 打赏
  • 举报
回复
ding
心留 2010-01-11
  • 打赏
  • 举报
回复
可以用vc调试一下,
或者在自己认为有可能出现错误的地方
messageBox()一下判断一下在哪句出的问题。
wolffan3150 2010-01-11
  • 打赏
  • 举报
回复
多半是readCard(com2,...)的问题,
可能用的方式有点不对,
要不就是readCard(com2,...)本身
就有bug,

建议注释掉readCard(com2,...),
测试下线程,
如果没问题就是readCard(com2,...)的问题了
sandyandy 2010-01-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 mazm_yanzhu 的回复:]
单步调试,最好的手段,代码也很短,应该很快就找到了
[/Quote]

yes
red-fly 2010-01-11
  • 打赏
  • 举报
回复
是不是红色那一行把程序塞住了?
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 ziplj 的回复:]
try catch(...)
一般线程自动退出时有异常发生的 

[/Quote]

加了,但是根本就没有执行到CATCH里面


我放源代码
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
还有个现象:

在用户现场,就出问题,但是在公司就不出问题(为了便于找出问题,专门讲用户现场用的机器弄到公司)

………………
wjx_0_2001 2010-01-11
  • 打赏
  • 举报
回复
vc 6.0中怎么没看到这个在哪儿设置?

不会么有吧
cnzdgs 2010-01-11
  • 打赏
  • 举报
回复
用try...catch时项目是否设置了启用SEH异常(/EHa)?
wjx_0_2001 2010-01-06
  • 打赏
  • 举报
回复
继续

别沉底啊

各位
ziplj 2010-01-06
  • 打赏
  • 举报
回复
try catch(...)
一般线程自动退出时有异常发生的
cnzdgs 2010-01-06
  • 打赏
  • 举报
回复
我前面说的放在try{}里面捕获异常,试过了吗?你没回应我也没法继续。
wjx_0_2001 2009-12-30
  • 打赏
  • 举报
回复
肯定是进入了while中,不然不会一直写日志的。更不可能读卡了

wjx_0_2001 2009-12-30
  • 打赏
  • 举报
回复
因为这个现象,不是很有规律的出现,有可能一天都没问题

有可能,刚开程序,就读不出卡来

也可能,刚执行一会,才出问题

所以,你根本不知道它什么时候会出现
===========================
我在公司将程序以调试状态执行,当出问题后,我在死循环中加断点,没有反应


所以就如CNZDGS说的那样,可能线程已经异常退出
bragi523 2009-12-30
  • 打赏
  • 举报
回复
那你单步的时候到底有没有进到while里面啊?
wjx_0_2001 2009-12-30
  • 打赏
  • 举报
回复
不是,因为从日志来看,这块就没执行
加载更多回复(7)
代码下载地址: https://pan.quark.cn/s/8236006bf1f9 Word精灵插件:一款用于增强Microsoft Word功能的辅助软件,能够将多种复杂功能转化为插件形式,并在软件状态栏中进行展示,涵盖诸如批注管理、表格处理、内容替换、文档拆分、数学运算、字符提取、批量重命名等多项实用工具。在工作环境中应用该插件能够显著降低工作强度,提升操作效率。Word精灵插件兼容32位与64位的Microsoft Word版本,支持Word 2007、2010、2013以及Word 2016操作系统,但不适用于Word 2003版本。此外,该插件同样支持WPS办公软件。 功能概述: 1、表格自动调整宽度:自动优化文档内所有表格的显示宽度。 2、批量导出批注信息:将文档内所有批注集中导出到Excel工作簿中。 3、表格至Excel多表导出:在将表格导出到Excel时,每个Word表格将独立存放在一个工作表中,Word文档内的表格数量与Excel生成的工作表数量相等,并附有工作表目录。 4、表格至Excel单表导出:将文档内所有表格整合后导出到一个Excel工作表中,多个表格将按顺序排列于同一工作表内。 5、统一图片分辨率:对指定文件夹内的所有图片进行分辨率标准化处理。 6、图片批量缩放:依据设定比例对图片进行放大或缩小,支持按百分比调整。 7、图片批量插入:将图片批量插入到当前文档,可选择图片名称的展示形式,并设定图片的高度。 8、图片格式统一转换:将指定文件夹内的所有图片转换为相同的文件格式。 9、内容批量替换:对文档内容、页眉及页脚执行批量替换操作,例如将数字1替换为字母A,数字2替换为字母B,数字3替换为字母C等。 10、图片批量导出:将文档内所...
打开链接下载源码: https://pan.quark.cn/s/245ca7a27256 OmniGraffle是一款效能卓越的图形设计软件,在构建图表、流程图以及组织结构图等领域的应用尤为突出。该软件起源于Mac操作系统,并且兼容iOS平台,作为专业人士及业余爱好者进行图形设计时的首选工具之一。在OmniGraffle的功能模块中,“泳道图流程图”占据着核心地位,它主要用于勾勒业务流程图或系统流程图,其中各个分隔的泳道象征着不同的职能角色、部门划分或工作流程的各个阶段。泳道图(Lanes Diagram)作为流程图的一种特殊形式,通过将流程中的各个操作步骤分配到垂直或水平的“泳道”之中,能够明确地揭示出每个参与方或部门所承担的责任以及整个流程的走向。此类图形通常应用于业务流程管理(BPM)和系统分析领域,旨在帮助用户深入理解并优化复杂的业务流程。 在OmniGraffle中构建泳道图时,由于软件本身并未提供现成的泳道图模板,用户需要自行设计图形和布局以模拟出泳道的效果。然而,您提供的"06stencil泳道图流程图.graffle"文件很可能是一个预先构建好的模板,能够显著简化这一过程。该模板可能包含了预先设计好的泳道形态、箭头以及其他流程图组件,使用户能够直接在此基础上进行修改和增添个人的步骤,从而节省了大量的设计时间。 应用OmniGraffle的泳道图模板,你可以: 1. **导入模板**:首先需要启动OmniGraffle并将"06stencil泳道图流程图.graffle"文件添加到你的项目工作中。 2. **定制泳道**:依据实际需求调整泳道的数量和尺寸,使之契合你的业务流程。每个泳道对应一个角色或部门,确保它们的排列顺序和宽度能够精确地体现实际的工...

15,465

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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