1

私は何らかの仕事をするためにスレッドを開始する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;

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 でスタック オーバーフローが発生しました。中断モードでの割り当てがスタックを台無しにする可能性があるのか​​ 、それともインディに問題があるのか​​ どうか疑問に思います。マネージド コードとアンマネージド コードが混在しているときに例外がマスクされていない場合、問題が発生する可能性があることをお読みください。これが関係しているかどうかはわかりません。注: 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でラップしましたが、それはスレッドではなくメインプロセスでのみ機能すると思うので、次のコードのように実装したHandleExceptionを呼び出すEventMesssenger.Executeのコードの周りにtry/exceptを追加しました、ただし、ExceptionHandlerに入らずにAVでサービスがクラッシュします。

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;
4

2 に答える 2

1

あなたの質問に答えるにAssign()は、スレッドが中断されている間は問題なく動作します。Assign()のメソッドのように、スタックに触れていませんTPersistent。Delphi オブジェクトは、スタックではなくヒープ上に存在します。

通常、スタック オーバーフローは、終了していない再帰関数呼び出しが発生したことを意味します。デバッガーでコードを実行し、オーバーフローが発生したときにコール スタックを調べます。これは、再帰ループでスタックしている関数を診断するのに役立ちます。

于 2013-08-08T17:56:50.290 に答える
0

ここで私の答えを見つけました.Microsoftが削除するのを忘れていたハードコードされたブレークポイントに関係していたようです. Rad Studio デバッガー スレッドで未処理の例外

于 2013-08-19T12:05:48.883 に答える