ParkingWindow

WindowsFormアプリケーションでいろいろな処理を行っていると、生成した覚えの無い"WindowsFormsParkingWindow"という名の不可視のウインドウに遭遇する時がある。便宜上、このウインドウを"パーキングウインドウ"と呼ぼう。

調べた所、パーキングウインドウは.NETでウインドウを扱う際に、親のウインドウが無いウインドウ(Windowsの世界では許されない)が論理的に発生してしまった場合に、親無しのウインドウを一手に預かる役目をしているグローバルなウインドウらしい。
そんなことが起こりうるのかといえば、.NET C#のようなオブジェクト指向なラィブラリィでは簡単に起こりうる。一番単純なのはFormクラス(System.Windows.Forms.Form)においてControlを追加した後に削除した時だ。

Form form = new Form1();
TextBox txtBox = new TextBox();
form.Controls.Add(txtBox);
form.Controls.Remove(txtBox);

最後のRemoveメソッド実行後、txtBoxの親はformからパーキングウインドウに変更されるらしい("らしい"と書いたのはソースコードが無く、真偽が証明できないからだ)

これ自体はWin32がそもそもオブジェクト指向の前時代に作られたAPIなため、オブジェクト指向言語とのインピダンスミスマッチを吸収するための仕組みであり仕方がないのだが、認識していないウインドウが列挙されるのは気持ちが悪いものだ。
なお、このパーキングウインドウ、デバッグ中はVisual StudioのHostingProcess経由である{Microsoft.VisualStudio.HostingProcess.ParkingWindow}という名前のクラスで検知されたりするのだが、これが.NETの通常のUIスレッドで生成されているわけでは無いようで、その後、同期化無しに操作をしようとしただけで例外が投げられてしまうのが困った所である。
パーキングウインドウが検知されるのを見越してその処理を同期化するか、又は同ウインドウは処理から除外するように作りこむか、悩む所だ。
あと、注意すべきはこのコードでControlCollectionから取り除かれたTextBoxクラスのインスタンスは、GCの対象にはならない、ということだ。コレクションから削除した後に使用しないのであればとっととDisposeすべきだろう。

追記
「ハンドルを持つリソースがGCの対象にならない」、というのは誤った記述でしたので、該当の文言を削除しました。