バックグラウンド:
もともと .NET 1.1 で作成され、Visual Studio を介して .NET 4.0 に移行された WinForms アプリ。メイン アプリ フォームの上部にある典型的なメニュー バー (注: ToolStripMenuItem には移行されていません)。Exit メニュー項目を含む File メニュー項目があると予想されるかもしれません。
モーダル ロック フォームを表示する Ctrl-L ショートカットを実装しました。メイン フォームにはタイマー コンポーネントもあり、構成可能な時間のアクティビティがない場合に自動的にロック フォームが表示されます。
ロック フォームが表示されたら、ロックを解除する (ユーザーが再度ログインする必要がある) か、終了することができます。終了することを選択した場合、私のコードは fileExitMenuItem.PerformClick() 呼び出しを行います。
問題:
移行後に何らかの奇妙な理由で、自動的に、または Ctrl-L ショートカットによって表示されたロック フォームを終了すると、コードの fileExitMenuItem.PerformClick() 行で NullReferenceException がスローされます。
fileExitMenuItem は null ではありません。break-when-exception-throw をオンにすると、すべての fileExitMenuItems プロパティを参照できます。
フォームのデザイナー コードを中断して、クリック イベント ハンドラーがアタッチされているのを確認できます。[ファイル] >> [終了] メニュー項目を直接使用すると、イベント ハンドラーのコードを中断できます。
つまり、これは完全な WTF の瞬間です。何を見るべきかについての提案は大歓迎です
[更新 1] 要求されたコードは次のとおりです。このメソッドは、ユーザーが Ctrl-L を押すか、ロック タイマーが経過するたびに呼び出されます。
private void LockApplication()
{
try
{
// Stop the timer so we don't get any more elapsed events whilst we are waiting
// for a user to respond to the lockdown dialog. In addition stop the callout reminder
// time as once we have locked we don't want that doing it's thing.
lockdownTimer.Stop();
calloutsReminderTimer.Stop();
// Clone the current identity so we can check it later.
var previousIdentity = (CudosIdentity)BOUtilities.CurrentIdentity.Clone();
// Show lockdown form.
System.Windows.Forms.DialogResult result;
using (var lockForm = new Forms.applicationLockedForm())
result = lockForm.ShowDialog(this);
if (result == DialogResult.OK)
{
// Did we unlock with a different login?
if (!previousIdentity.Equals(BOUtilities.CurrentIdentity))
{
// Yes, so lose all changes.
CloseOpenForms();
if (_currentLoadSpec != null)
_currentLoadSpec.CancelContent();
}
RefreshLockTimerSetting(null);
}
else
fileExitMenuItem.PerformClick();
}
catch (Exception ex)
{
Helper.LogError(ex);
}
finally
{
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
}
これは終了メニュー項目のコードです:
private void fileExitMenuItem_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
上記の LockApplication メソッドの次の行が呼び出されると、NullReferenceException が発生します。
fileExitMenuItem.PerformClick();
[更新 2] 上記の行が実行されたときのコール スタック情報:
[External Code]
Cudos.exe!Cudos.mainForm.LockApplication() 1132 行 + 0x10 バイト C# Cudos.exe!Cudos.mainForm.fileLockCudosMenuItem_Click(object sender, System.EventArgs e) 1594 行 + 0x8 バイト C# [外部コード] Cudos.exe!Cudos .mainForm.Main() 1880 行目 + 0x1d バイト C# [外部コード]