C#:ToolStripDropDown がハンドルを破棄/破棄しない
-
26-10-2019 - |
質問
私が使っているのは、 ToolStripDropDown
選択ポップアップを表示します。
の ToolStripDropDown
実行中のスレッドを含むいくつかのカスタム コントロールが含まれています。スレッドは OnHandleDestroyed イベントで終了しますが、何らかの理由で ToolStripDropDown
閉じた後にハンドルを破棄/破棄しません。
を処分する ToolStripDropDown
Closed-event では、依然として ToolStripDropDown にアクセスするものがあるため、例外が発生します。
スレッドを終了するには、カスタム コントロールがまだ使用中かどうかを確認するにはどうすればよいですか?
カスタムコントロール:
public class CControl : Control
{
Thread StyleThread;
Object lockOBJ = new Object();
bool abortthread = false;
public CControl()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.Selectable, false);
StyleThread = new Thread(new ThreadStart(this.StyleDelegate));
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
if(!StyleThread.IsAlive)
StyleThread.Start();
}
protected override void OnHandleDestroyed(EventArgs e)
{
base.OnHandleDestroyed(e);
lock (lockOBJ)
{
abortthread = true;
}
if (StyleThread.IsAlive)
{
StyleThread.Join(100);
}
}
...
}
ToolStripDropDown コントロール:
public class AddPopUp : UserControl
{
/*
------------------------------------
This Control contains some CControls
------------------------------------
*/
public void Show(Control control)
{
TSDD tsdd = new TSDD(this);
Point screenpoint = control.PointToScreen(new Point(0, 0));
tsdd.Show(control,new Point(0, -tsdd.Height ));
}
class TSDD : ToolStripDropDown
{
private Control Control { get; set; }
public TSDD(Control control)
{
this.Control = control;
this.DropShadowEnabled = false;
ToolStripControlHost ch = new ToolStripControlHost(control);
this.Items.Add(ch);
}
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
base.SetBoundsCore(x, y, Control.Size.Width + 16, Control.Size.Height + 18, specified);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
unchecked
{
cp.Style |= (int)0x80000000;
cp.Style |= 0x40000;
}
return cp;
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x84)
{
m.Result = (IntPtr)1;
return;
}
base.WndProc(ref m);
}
}
}
編集:
さらに同じテストを行った後、toolstripdropdown を破棄できませんでした。回避策として、ツールストリップドロップダウンを閉じるときにハンドルを破棄するだけです。
protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
{
base.OnClosed(e);
this.DestroyHandle();
}
解決
ToolStrips には、ユーザーが OS のグローバル スタイル設定を変更した場合に再描画できるように、SystemEvents.UserPreferenceChanged にイベント ハンドラーを登録する非常に永続的なバグがあります (修正されたと主張されていますが、まだ問題があります)。
私が見つけた唯一の回避策は、SystemEvents.UserPreferenceChanged 内のハンドラーを列挙し、コントロールの破棄時にハンドラーを削除することで、添付されたツールストリップを削除することです。
http://connect.microsoft.com/VisualStudio/フィードバック/詳細/115600/toolstrip-leaks-after-calling-dispose#