Forms
ウィンドウをダイアログボックスとして表示しています
private void buttonOverview_Click(object sender, EventArgs e)
{
(new OverviewBox()).ShowDialog();
MessageBox.Show("Window Exited");
}
OverviewBox
コンストラクター内でインスタンス化されるリフレッシュ タイマーがある
public OverviewBox()
{
InitializeComponent();
this._polltimer = new Timer { Interval = 30000, Enabled = true };
this._polltimer.Tick += (sender, e) => { this.Poll(); };
}
メソッドPoll
は非同期的にデータベースからデータを取得し、ビューをフリーズせずに更新します。
private void Poll()
{
Task.Run(() =>
{
if (!SessionContext.Connectable())
{
return;
}
try
{
[logics to get data]
this.dgvChangeCoordinators.BeginInvoke(new Action(() => { SetDataGridView(this.dataGridView, "<Data Description>", listwithdata); }));
}
catch (Exception ex)
{
Logger.Log(ex.ToString());
throw;
}
});
}
SetDataGridView
itemsource
の時点でリストを設定しdatagridview
、データの説明を表示します。ただし、ユーザーが例外について不満を言うことがあります。例外ログは次のようになります。
7/15/2013 5:00:10 PM:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.BeginInvoke(Delegate method)
at FormulierGenerator.Views.Agent.OverviewBox.<Poll>b__5()
7/15/2013 5:00:23 PM:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.BeginInvoke(Delegate method)
at FormulierGenerator.Views.Agent.OverviewBox.<Poll>b__5()
7/15/2013 5:00:40 PM:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.BeginInvoke(Delegate method)
at FormulierGenerator.Views.Agent.OverviewBox.<Poll>b__5()
7/15/2013 5:00:53 PM:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.BeginInvoke(Delegate method)
at FormulierGenerator.Views.Agent.OverviewBox.<Poll>b__5()
例外間の時間差から、タイマーの少なくとも 2 つのインスタンスがまだアクティブであると結論付けます (ポーリング間の 30 秒、2 つのグループが 30 秒以内にある 4 つの異なる時間、ポーリング間隔)。ただし、概要を 2 回開始して閉じるだけでは、問題をシミュレートすることはできません。
GC
ウィンドウ オブジェクトがある時点で収集されるが、ポーラーが存在し続けるという関連する問題が疑われます。ウィンドウ スレッド コンテキストでウィンドウを更新しようとすると、失敗します。しかし、 Window オブジェクトとそのすべてのコンテンツは、 private void のコンテキストにのみ存在するべきではありませんbuttonOverview_Click
か? ボタン メソッドに MessageBox.Show() 呼び出しを追加して、ダイアログを閉じた後にメソッドが完了したかどうかをテストしました。それは示しています。
メソッドにブレークポイントを設定してPoll
、ダイアログが閉じられた後もメソッドが呼び出されているかどうかを確認します。そうだったので、ポーラーは間違いなくウィンドウが表示されているよりも長く生きています。私の質問は、これまでのところ私の結論は正しいですか? もしそうなら、タイマーを作成するオブジェクトがインスタンス化されたコンテキストが存在しなくなったとしても、ポーラーはどのように存在し続けることができますか? アンロード イベント アクションを考えていますが、それが最善の解決策かどうかはわかりません。