-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,因爲它遠不是最小的,因此,這個問題可能有問題,儘管我認爲答案包含其他人的有用信息。 –