一个delphi死循环的问题(300分)

  • 主题发起人 主题发起人 vicchen0
  • 开始时间 开始时间
V

vicchen0

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序有这样一段代码:
while Scan_IsButtonDown() = false do
begin
Application.ProcessMessages; //释放CPU
end;
上边的Scan_IscButtonDown是用外部设备传递过来的消息,如果没有按钮他就一直在死循环,现在我想在界面上做一个退出按钮,就是说如果我按钮那个退出按钮就退出程序,上边的代码是在下面这段程序里边的。

还有别一个关于Dll文件加载的问题,我想问下面的这段代码,如果我的DLL文件加载不成功,我想他可以再刷次就使用,要怎么做才可以呢?还有就是如果识别失败的话,我的程序就再也不能用了,程序就一直死在那里,请问有什么方法可以释放那个DLL文件然后再重新加载呢?或者说如果在“识别失败”后能够再次能够再识别,我现在的情况是一失败之后,整个程序就再也不能用了,无论怎么按也没有反应的
procedure TForm1.Button1Click(Sender: TObject);
var
result: Integer;
I: Integer;
j: Integer;
bGoon: WordBool;
length: Integer;
strImageFile: AnsiString;
strHeadFile: AnsiString;
strResult: string;
buffer: PChar;
len: Integer;
HInst: THandle;
//--------函数指针--------------------------------------
FPointer: TFarProc;
LoadIdcardLibrary: TLoadIdcardLibrary;
Scan_IsButtonDown: TScan_IsButtonDown;
RecogIdcard: TRecogIdcard;
FreeIdcardLibrary: TFreeIdcardLibrary;
//-------------------------------------------------------
pSysDir:PChar;
SysDir:String;
begin
//--------取得系统目录,之前已将扫描驱动相关文件拷贝到这个目录下
GetMem(pSysDir,80);
i:=GetSystemDirectory(pSysDir,80);
if i<80 then
pSysDir:=#0;
SysDir := StrPas(pSysDir);
FreeMem(pSysDir);
SetCurrentDir(SysDir);//设置软件运行目录为系统目录
HInst := LoadLibrary(PChar(SysDir+'/idcarddll.dll'));//加载驱动DLL
if HInst > 0 then//如果加载成功
begin
try
FPointer := GetProcAddress(HInst, 'LoadIdcardLibrary');//指定函数指针
if FPointer <> nil then
begin
LoadIdcardLibrary := TLoadIdcardLibrary(FPointer);//类型转换
FPointer := nil;
end;
FPointer := GetProcAddress(HInst, 'Scan_IsButtonDown');
if FPointer <> nil then
begin
Scan_IsButtonDown := TScan_IsButtonDown(FPointer);
FPointer := nil;
end;
FPointer := GetProcAddress(HInst, 'RecogIdcard');
if FPointer <> nil then
begin
RecogIdcard := TRecogIdcard(FPointer);
FPointer := nil;
end;
FPointer := GetProcAddress(HInst, 'FreeIdcardLibrary');
if FPointer <> nil then
begin
FreeIdcardLibrary := TFreeIdcardLibrary(FPointer);
FPointer := nil;
end;
//加载识别核心
if (LoadIdcardLibrary() = 0) then
begin
Edit2.Text := '成功初始化,请按扫描机器上的按钮进行扫描!' ;
button1.Enabled:=false;

EditName.Text := '';
EditSex.Text := '';
EditMZ.Text := '';
EditBD.Text := '';
EditAddr.Text := '';
EditID.Text := '';
EditName.Refresh;
EditSex.Refresh;
EditMZ.Refresh;
EditBD.Refresh;
EditAddr.Refresh;
EditID.Refresh;

//进行识别
length := 31;
bGoon := True;
while bGoon do
begin

strImageFile := 'd:/ID00';
strImageFile := strImageFile + IntToStr(num);
strImageFile := strImageFile + '.jpg';
strHeadFile := 'd:/ID00';
strHeadFile := strHeadFile + IntToStr(num);
strHeadFile := strHeadFile + '_head.jpg';

while Scan_IsButtonDown() = false do
begin
Application.ProcessMessages; //释放CPU
end;
Edit2.Text := '正在扫描...';
Edit2.Refresh;
result := RecogIdcard(strImageFile, @MyCard, True, 0, length,
strHeadFile);
//image1.Picture.LoadFromFile( strImageFile);
if (result = 0) then //识别成功
begin
num:=num+1;
//写姓名
Editname.Text := 姓名;
//写性别
EditSex.Text := 性别;
Edit2.Text := '成功识别!';
end
else //识别失败
begin
Edit2.Text := '识别失败!';
button3.Enabled:=false;
button1.Caption:='重新扫描';
button1.Enabled:=true;
exit;
end;
bGoon := true;

end;
FreeLibrary(HInst);
end
else
begin
Edit2.Text := '初始化失败,请刷新网页!';
end;
finally
FreeLibrary(HInst);//释放驱动DLL
end;
end
else
ShowMessage('不能装载“idcarddll.dll” 文件');

end;
 
提前。。。。。。
 
问题一、因为您的程序本身是‘死’的,所以只能这样
现在外设没有这样的,不能一直在循环中检测。。。。
一般是外设有中断请求信号--响应中断--处理。。。。。。
 
但这个设备是其它公司提供的,而且我们只提供给我们DLL文件,现在我想优先解决的问题是,如果加载失败或初始化失败后,如果再按钮就可以再重新加载文件完成初始化的工作
 
我想问一下,如果用多线程可以解决这个死循环的问题呢?
 
while Scan_IsButtonDown() = false do
begin
Application.ProcessMessages; //释放CPU
//更正,这个过程不是释放CPU,是让程序处理 Windows 消息
if toExit then //toExit 你自己设一个控制变量
Break; // 跳出循环
end;
==================================================================
toExit 初始化为 False; 它的值用也就是你所说的退出按钮来控制赋值
按下按钮就 toExit := True;
在程序运行到 if toExit then 这句之前,ProcessMessages 会处理退出按钮的过程

顺便说一下 while Scan_IsButtonDown() = false do 是有问题吧
因该是 while not Scan_IsButtonDown() do
 
我个人认为是你没有找到对应的函数.
一般设备提供 初始化设备函数,
读取函数, 触发函数之类的.
如果你非要实现时时监控,可以这样考虑.
用timer事件来实现.

一般情况下初始化设备只要程序一开始的时候初始化就可以了.
不用读一个人的信息就初始化设备一次.
 
主要问题是这段程序是设备提供商给我们的例程来的,因此还有很多问题没有解决啦,至于那个程序的初始化,我现在还是搞不太懂啦,我也试过让他在程序开始时初始化,但如果根据上边的程序初始化,主界面是不能出来的呢,一直在循环里边不出来啦
 
了解一下外设的API
 
如果可以的话,请各位大虾先帮我解决一下就基本的初始化问题吧,我现在是不知道如果释放那个DLL文件啦,这个问题占100分呢
 
1. while Scan_IsButtonDown() = false do
如果Scan_IsButtonDown()不是查询一下就返回,而是一直在等输入,你的这段程就跟没写一样,白费了功夫。
如果你把Scan_IsButtonDown() 放到线程中,主线程不死了,可以响应输入,但关闭又成了问题,它总是不出来,线程又关不掉。
用Timer也一样,连Timer也拖死了。

2.看你的代码,Scan_IsButtonDown() 是DLL中的函数,死循环在DLL中了。好像没法强行释放DLL.

给个建议:
1.看厂家给的例程,看看有没有遗漏的地方,比如:函数调用、参数设置等;
2.实在不行,别自己折腾了,找厂家的人帮忙;最起码Scan_IsButtonDown()函数应该由化们自己加ProcessMessages.
 
while bContinue AND NOT(Scan_IsButtonDown()) do
begin
Application.PorcessMessage();
end;

界面加一个按钮,触发的时候写
bContinue:=False;
 
楼上:
主线程都死锁在Scan_IsButtonDown()中了,如何响应你按键的消息。
 
如果Scan_IsButtonDown 真的是锁死了,神仙也没有办法(应该是Bug,不应该锁死);
---------------------------------
看来是要用到线程,因为你的 Scan_IsButtonDown 是 DLL中的函数,
开一个线程监测Scan_IsButtonDown 的状态(最好将 优先权 设置为低,可以减少对主线程的影响),如果监测成功,返回提示,否则不断监测!
procedure TxThread.excuted;
begin
while Scan_IsButtonDown and (not Terminal) do...
end;

在主线程中,按 cancel 按钮就中止监测线程,xThread.terminal
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
740
import
I
I
回复
0
查看
478
import
I
I
回复
0
查看
720
import
I
后退
顶部