你是否可以为挂起线程上的对象调用assign函数?

时间:2013-08-08 10:23:20

标签: multithreading delphi overflow delphi-2009 indy10

我有一个Windows服务项目启动一个线程来做一些工作,这部分已经工作了很长时间,所以不是问题的一部分。我想要做的是当这个工作开始和结束时,它应该启动另一个线程(继承TThread的EventMessenger)来发送电子邮件,其中包含有关工作已经开始和结束的通知。我知道你不能有嵌套线程,但我认为从另一个线程启动一个线程应该没问题,那么它只属于主进程。我在挂起模式下创建线程,但我不确定是否可以在线程对象暂停时为对象调用assign。

EventMessenger := TEventMessenger.Create(true); // true = start suspended
EventMessenger.StatusCode := AStatusCode;
EventMessenger.Receiver.Assign(Receiver);
EventMessenger.MessageOptions.Assign(MessageOptions);
EventMessenger.MessageDetails := AMessage;
EventMessenger.FreeOnTerminate := true;
EventMessenger.Resume;

Execute for TEventMessenger使用Indy TIdSmtp发送邮件,这里是代码的一部分

try
  self.FMessage.From.Address := ASender;
  self.FMessage.Recipients.EMailAddresses := AReceiver;
  self.FMessage.Subject := ASubject;
  self.FMessage.Body.Text := AMessage;
  try
    self.FSMTP.Connect;
    self.FSMTP.Send(self.FMessage);
  except
    on E:EIdException do
    begin
      CurrentEurekaLogOptions.ExceptionDialogOptions := []; // Don't show dialog box
      StandardEurekaNotify(E, ExceptAddr()); // Save exception to file
    end;
  end;
finally
  if self.FSMTP.Connected then
    self.FSMTP.Disconnect;
end;

我第一次启动线程EventMessenger时工作正常,并发送一封关于工作已开始的电子邮件。但是,当它再次启动EventMessenger以发送有关作业停止的邮件时,我在ntdll中出现了堆栈溢出。我想知道在挂起模式下的分配是否会弄乱堆栈或indy中是否存在某些问题;如果在混合托管/非托管代码时没有屏蔽异常,那么可能会出现问题,不确定这是否与它有关。注意:我没有在Delphi 2009中使用默认的Indy,因为它有几个错误,我正在运行从1月份从其存储库下载的Indy10代码。

:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll
:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll
:779e010f ntdll.KiUserExceptionDispatcher + 0xf
:77a2878b ; ntdll.dll

任何人都知道导致堆栈溢出的实际问题是什么,或者我如何捕获异常?我已经在try / except中包装了indy send,但我想这只适用于主进程而不是线程,所以我还在EventMesssenger.Execute中添加了一个try / except代码,它调用了我实现的HandleException,如下面的代码但是,如果没有进入ExceptionHandler,它的服务就会崩溃。

procedure TEventMessenger.DoHandleException;
begin
  if FException is Exception then
  begin
    CurrentEurekaLogOptions.ExceptionDialogOptions := []; // Don't show dialog box
    StandardEurekaNotify(FException, ExceptAddr()); // Save exception to file
  end;
end;

procedure TEventMessenger.HandleException;
begin
  FException := Exception(ExceptObject);
  try
    if not (FException is EAbort) then
      Synchronize(DoHandleException);
  finally
    FException := nil;
  end;
end;

2 个答案:

答案 0 :(得分:1)

要回答您的问题 - Assign()在线程暂停时会正常工作。您没有触及堆栈,因为Assign()TPersistent的方法,并且堆栈中存在Delphi对象,而不是堆栈。

堆栈溢出通常意味着您遇到了永不结束的递归函数调用。在调试器中运行代码并在发生溢出时查看调用堆栈,这将帮助您诊断哪个函数在递归循环中卡住了。

答案 1 :(得分:0)

在这里找到我的答案,似乎它与硬编码断点微软已经忘记删除。 Unhandled Exception in Rad Studio Debugger Thread