如何防止控件破坏后的邮件处理

时间:2017-08-14 09:59:34

标签: delphi access-violation windows-messages object-destruction

以下组件类型有两个实例:

  1. TfrmTimeSliceStructure,是TFrame的直接后裔。
  2. THKSDBVirtualStringTree,是TDBVirtualStringTree(来自FIBPlus)的直系后裔,后者本身是Mike Lischke TVirtualStringTree班的直系后裔。
  3. THKSDBVirtualStringTree组件用作TfrmTimeSliceStructure上的子控件。

    双击 - 在某些条件下 - 框架应被销毁。

    为此,我使用自定义消息代码PostMessage进行WM_USER + 4调用(这是十六进制$0404),以便延迟销毁,直到完全处理所有当前消息。 / p>

    尽管在许多情况下会发生访问冲突,因为THKSDBVirtualStringTree组件在自身销毁后仍在处理邮件。

    我预计在控件的破坏后不会发生消息处理。

    如何防止已被销毁的控件处理邮件?

    下面,您可以看到调试器的输出。在这两个类中,我添加了一个消息,记录方法WndProc以输出收到的消息代码。在第一行中,可以看到我的自定义消息代码WM_USER + 4已收到。

    有些行后来有两行Instance of class THKSDBVirtualStringTree is going to be destroyed.Instance of class THKSDBVirtualStringTree has been destroyed.。在这两行之间,没有收到任何消息 在这些行之后,仍然会处理一些消息。最终,这会导致最后的访问冲突。从我们的消息代码我可以看到,这些消息是控制消息,因为CM_BASE = $B000;

    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $0404 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $0405 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $8001 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0200 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0202 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0215 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $02A3 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B014 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $B014 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $8001 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $8001 Prozess Memory.exe (20916)
    Thread-Start: Thread-ID: 6260. Prozess Memory.exe (20916)
    Thread-Start: Thread-ID: 21148. Prozess Memory.exe (20916)
    Thread-Ende: Thread-ID: 6260. Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $0002 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $000E Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0272 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0002 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $000E Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $0082 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class TfrmTimeSliceStructure recieved message $0082 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree is going to be destroyed. Prozess Memory.exe (20916)
    Thread-Ende: Thread-ID: 22156. Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree has been destroyed. Prozess Memory.exe (20916)
    Thread-Start: Thread-ID: 5672. Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B028 Prozess Memory.exe (20916)
    Thread-Start: Thread-ID: 9244. Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B009 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B008 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B023 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B03D Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B050 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B058 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B011 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B03B Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B03B Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B00D Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B022 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B009 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B008 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B023 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B035 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B03D Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B050 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B058 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B011 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B009 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B035 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B034 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B009 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B03B Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B008 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B00E Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B034 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B008 Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B00E Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B034 Prozess Memory.exe (20916)
    Thread-Ende: Thread-ID: 5672. Prozess Memory.exe (20916)
    Thread-Ende: Thread-ID: 21148. Prozess Memory.exe (20916)
    Debug-Ausgabe: Instance of class THKSDBVirtualStringTree recieved message $B007 Prozess Memory.exe (20916)
    Erste Gelegenheit für Exception bei $01819981. Exception-Klasse $C0000005 mit Meldung 'access violation at 0x01819981: read of address 0x00000050'. Prozess Memory.exe (20916)
    

1 个答案:

答案 0 :(得分:4)

问题是由Application.ProcessMessages事件处理程序代码中某处显式调用OnNodeDblClick引起的。

不幸的是,我们的代码库中仍然有一些调用。 : - (

让我告诉你我是如何找到问题的原因的:

正如您在问题中所看到的,我尝试了这两种方法:

  1. 覆盖控件的WndProc并使用OutputDebugString记录每个已处理的邮件。
  2. 检查控件是否已被销毁,方法是将一个调用添加到OutputDebugString到开头,另一个调用添加到控件析构函数的末尾。
  3. 后来,我想到了......

    1. ...检查是否已完全处理初始用户交互(此处:双击)。这也是OutputDebugString所做的 在我的情况下,在发生访问冲突之前没有完全处理第二次鼠标停止。
    2. 然后我可以得出结论,消息队列的某个地方过早地被处理了。所以,我必须找出,Application.ProcessMessages被称为。{/ p>

      1. 因此,我在此方法中添加了断点。因为正常的断点会破坏消息处理。我使用了另一个断点类型 - 我必须承认 - 我第一次使用它。
        在断点的高级设置中,我取消选择 Break 并选择 Log Call Stack 。我决定只记录两个堆栈帧,因为我只是想知道Application.ProcessMessages的直接调用者是谁。
      2. 经过另一轮复制后,我有一个广泛的调试器日志,其中包含所有处理过的消息代码和每次调用鼠标按下处理程序,对象的析构函数以及每次调用Application.ProcessMessages的行。

        1. 现在,我可以推断,在未完成的鼠标按下处理程序开始之后和接收我的自定义事件Application.ProcessMessages之前,对WM_USER + 4的第一次调用必须是那个,这打破了代码。