Delphi线程Suspend为什么停不下来?GetLastError获取的错误不能被try except捕获吗

xumenger 2016-05-06 11:07:35
GetLastError

GetLastError是获取调用系统API出现的报错信息
这种类型的错误能够被 try except 方式的异常机制捕获吗?

线程

使用Delphi实现的一个线程,代码如下
GetLastError获取的错误码是2,并没有捕获异常,但是线程持续运行,说明suspend没有起作用
另外,线程反复输出如下信息,并没有报错,说明压缩成功,走到suspend方法调用的代码行



正在压缩文件,请稍候...
压缩文件完成
GetLastError:2
正在压缩文件,请稍候...
压缩文件完成
GetLastError:2
正在压缩文件,请稍候...
压缩文件完成
GetLastError:2
....



为什么线程没有正常suspend而停止运行,反而是一直循环,根本停不下来


procedure TZipTask.Execute;
var
bSuccess: Boolean;
index: Integer;
iError: Integer;
begin
while not Terminated do
begin
try
index := GetCurrentThreadId;
SendMsg('正在压缩文件,请稍候...');
......//这里调用封装的一个压缩文件的API
if bSuccess then
SendMsg('压缩文件完成')
else
SendMsg('停止压缩文件');
except
on e:Exception do
begin
SendMsg('压缩文件出错' + E.Message);
end;
end;
bComplete := True;
Self.Suspend;
iError := GetLastError;
SendMsg('GetLastError:' + IntToStr(iError));
end;
end;
...全文
658 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
xumenger 2016-05-22
  • 打赏
  • 举报
回复
经过最终的排查,是因为在Windows Server2003的机器上,将进程设置为【兼容Windows95】方式运行 导致在这种情况下调用Windows的API方法SuspendThread无效 这个可以自己简单的实现一个程序进行验证!
SVIP_ 2016-05-10
  • 打赏
  • 举报
回复
是吃了炫迈吗
  • 打赏
  • 举报
回复
“设置Resume的地方只有一个”不代表Resume的执行次数和执行次序和Suspend是匹配的,你应该log Suspend和Resume的每次执行时间。
xumenger 2016-05-09
  • 打赏
  • 举报
回复
试了在压缩日志的地方SetLastError(2),但是线程可以正常suspend 检查代码程序设置Resume的地方只有一个,而且在客户现场排查的时候确认持续运行输出信息的线程就是一个线程
  • 打赏
  • 举报
回复
1. GetLastError只是返回当前线程保存的最后一次错误代码(由调用SetLastError设置),错误代码不代表出现异常,如果生成错误代码的函数里没有throw,就只是安静地返回一个错误代码。 2. 因为大部分API函数都设置错误代码,所以你把GetLastError写在这里是错误的: Self.Suspend; iError := GetLastError; Suspend在windows上的实现是调用API SuspendThread或者Wow64SuspendThread,所以你这里GetLastError的是它的SetLastError,而不是你的压缩函数设置的错误代码(如果它确实有调用SetLastError),另外TThread.Suspend内部也可能调用了GetLastError。 3. "Suspend为什么停不下来",估计是因为Suspend和Resume不匹配造成的,可能你调用Resume或者Start的次数多于Suspend,在windows上线程挂起和恢复是基于挂起计数的,SuspendThread增加计数,ResumeThread减少计数,计数为0线程运行,大于0则挂起。
xumenger 2016-05-07
  • 打赏
  • 举报
回复
Delphi的版本是6,现在的现象就是持续运行无法停止线程
hongss 2016-05-07
  • 打赏
  • 举报
回复
现在都用 MyThread.Suspended:= true; 这样的吧~~
看那山瞧那水 2016-05-07
  • 打赏
  • 举报
回复
while not Terminated do 一般不建议这样判断 suspend d7以后已经废弃了,不建议用。
xumenger 2016-05-07
  • 打赏
  • 举报
回复
现在的情况是,只有在客户的那一台机器上有问题,我们内部没有办法复现这个问题,之前是我在客户现场做的一些修改和尝试 但是因为现在已经回来了,想到的一些场景也没办法再去改代码给现场进行尝试了 如果GetLastError获取的错误码2,是在压缩文件的代码段中出现的问题,是不是因为GetLastError式的错误无法被普通的try except捕获?为什么? 如果GetLastError获取的错误码2,是在调用suspend的时候出现的,就可以解释为什么线程无法停止了,但是感觉不太可能,毕竟错误码2表示“系统找不到指定的文件”,看这个错像是在压缩文件的地方报出来的!
lyhoo163 2016-05-07
  • 打赏
  • 举报
回复

procedure TZipTask.Execute;
var
  bSuccess: Boolean;
  index: Integer;
  iError: Integer;
begin
  try
    index := GetCurrentThreadId;
    SendMsg('正在压缩文件,请稍候...');
    ......//这里调用封装的一个压缩文件的API
    if bSuccess then
      SendMsg('压缩文件完成')
    else
      SendMsg('停止压缩文件');
  except
    on e:Exception do
      SendMsg('压缩文件出错' + E.Message);
  end;
  bComplete := True;
  Self.Suspend;
  iError := GetLastError;
  SendMsg('GetLastError:' + IntToStr(iError));
end;
这样,试试。
mdejtod 2016-05-07
  • 打赏
  • 举报
回复
在线程外部挂起

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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