-2

有下列组件类型的两个实例:如何防止信息处理控制的破坏后

  1. TfrmTimeSliceStructure,这是TFrame的直系后裔。
  2. THKSDBVirtualStringTree,它是TDBVirtualStringTree(来自FIBPlus)的直系后代,它本身是Mike Lischke的TVirtualStringTree类的直系后裔。

THKSDBVirtualStringTree组件用作TfrmTimeSliceStructure上的子控件。

双击 - 在特定条件下 - 框架应被销毁。

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

虽然在很多情况下会发生访问冲突,因为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) 
+2

很难给这里的一般建议。如果我遇到了这个问题,我想要调试复制品。 –

+0

@DavidHeffernan我会尝试提供一个MCVE。但是在控件被破坏之后,我的消息处理没有发生,至少是正确的吗? –

+0

您是否尝试过调用帧的释放方法而不是免费?这是为了达到这个目的。 (我不知道这是否能解决问题,只是一个想法 – dummzeuch

回答

4

的问题是由一个显式调用我们OnNodeDblClick事件处理代码造成Application.ProcessMessages地方。

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


让我告诉你我是怎么发现了这个问题的原因:

正如你在这个问题看,我想这两种方法:

  1. 覆盖控制的WndProc并记录每个已处理的消息OutputDebugString
  2. 检查控制是否已被销毁,通过将一个呼叫添加到OutputDebugString开始和另一个结束您的控制的析构函数。

后来,就来到了我的脑海里......

  • ...检查,是否发起用户交互(这里:双击)已被处理完全。这也是用OutputDebugString来完成的。
    在我的情况下,在发生访问冲突之前,没有完全处理第二次鼠标放置。
  • 我可以得出结论,即某个地方的消息队列过早处理。所以,我必须找出,在哪里调用Application.ProcessMessages

    1. 因此,我在此方法中添加了一个断点。因为正常的断点会破坏消息处理。我使用了另一种断点类型 - 我必须承认 - 我第一次使用它。
      在断点的高级设置我取消选择中断并选择日志调用堆栈代替。我决定只记录两个堆栈帧,因为我只是想知道谁是Application.ProcessMessages的直接呼叫者。

    另一轮再生后,我包含所有这些处理消息码和线每次调用鼠标按下处理程序,对象的析构函数和每次调用Application.ProcessMessages广泛调试日志。

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

    很难理解你为什么写这个答案,我们没有复制品,问题中的信息不会导致这种情况,你可以通过提供一个[mcve]在这个问题上,但这还没有完成 –

    +0

    我写了这个答案,因为很难到达那里,这只是一个不好的行,导致了这个问题,我发现它有助于其他类似*问题知道一个方法来调试这样的问题我不能提供一个真正的MCVE,因为它远不是最小的,因此,这个问题可能有问题,尽管我认为答案包含其他人的有用信息。 –