はじめに
・ボタンを1回押しただけなのに処理が2回動く
・画面を開き直したらイベントが増えていく
・なぜかAPIが複数回呼ばれる
👉 こんな経験ありませんか?
WPFでは、
👉 「イベントの多重登録」
でハマることがよくあります。
しかも厄介なのが、
👉 コードを見てもすぐ気づきにくい
ことです。
この記事では、
👉 WPFでよくあるイベント多重実行パターン
を、実務でよくあるケースベースで整理します。
よくある症状
例えばこんな状態です。
button.Click += OnClick;
これ自体は普通です。
でも、
・画面を開き直したあと
・初期化をやり直したあと
・再読み込みしたあと
に、
👉 同じイベントがもう一度登録される
すると、
👉 1回押しただけなのに2回動く
という状態になります。
なぜ気づきにくいのか
ここが重要です。
多くの場合、
👉 「処理の中身」を疑ってしまう
からです。
例えば、
・APIが重複してる?
・DB更新がおかしい?
・非同期処理の問題?
と考えます。
でも実際には、
👉 “入口が2回登録されている”
だけだったりします。
パターン① Loadedイベントで毎回登録している
一番多いパターンです。
private void Window_Loaded(object sender, RoutedEventArgs e)
{
button.Click += OnClick;
}
これ、
👉 Loadedのたびに登録されます
つまり、
・画面再表示
・タブ切り替え
・再生成
などで、
👉 イベントが増殖する
症状
1回目 → 1回実行
2回目 → 2回実行
3回目 → 3回実行
👉 どんどん増える
対策
登録前に解除する。
button.Click -= OnClick;
button.Click += OnClick;
または、
👉 Loadedごとに登録しない構造にする
パターン② ViewModel生成時にイベント解除していない
MVVMでかなり多いです。
eventAggregator.SomeEvent += OnEvent;
これを登録したまま、
👉 ViewModelを破棄していない
すると、
👉 古いViewModelもイベントを受け取り続ける
症状
・閉じた画面の処理が動く
・昔のデータが更新される
・メモリリークする
なぜ怖い?
ここかなり重要。
コード上では、
👉 「今の画面だけ動いてるように見える」
でも実際には、
👉 裏で古いインスタンスも動いてる
対策
不要になったら解除。
eventAggregator.SomeEvent -= OnEvent;
または、
👉 Disposeで管理する
パターン③ Command内でイベント登録している
これも実務でかなりあります。
private void Execute()
{
service.Completed += OnCompleted;
}
Executeが呼ばれるたびに、
👉 Completedが追加登録される
症状
・処理完了時に複数回呼ばれる
・同じメッセージが何回も表示される
・ログが増殖する
なぜハマる?
ここ重要。
多くの場合、
👉 「処理の流れ」は正しい
だからです。
でも、
👉 “イベント登録の寿命”
を意識できていない。
重要なのは「どこで登録し、いつ解除するか」
イベントは、
👉 登録したら終わり
ではありません。
重要なのは、
・いつ登録する?
・いつ不要になる?
・誰が管理する?
です。
「処理が2回動く」の正体
実は、
👉 同じ処理が2回呼ばれている
とは限りません。
多くの場合、
👉 「入口」が複数ある
だけです。
つまり、
処理異常
↓
ではなく
イベント多重登録
だったりします。
調査するときの見方
もし、
👉 「なぜか2回動く」
状態になったら、
まず確認するのはこれです。
✔ イベント登録箇所
+=
を検索。
✔ Loaded / Initialize
何回呼ばれるか確認。
✔ ViewModel生成回数
同じものが増えていないか。
✔ Disposeされているか
不要なイベントが残っていないか。
まとめ
WPFでイベントが多重実行される原因の多くは、
👉 イベントの多重登録
です。
特に多いのが、
・Loadedで毎回登録
・ViewModel破棄漏れ
・Command内登録
です。
そして重要なのは、
👉 「処理がおかしい」
ではなく、
👉 「入口が増えている」
可能性を疑うことです。
✔ 1つだけ意識するなら
👉 「このイベント、いつ解除される?」
これを意識するだけで、
👉 多重実行はかなり防げます
おわりに
WPFでは、
👉 イベントの寿命管理
がかなり重要です。
特にMVVMでは、
・View
・ViewModel
・イベント
・非同期処理
が複雑に絡むため、
👉 「いつ生まれて、いつ消えるか」
を意識しないとハマりやすくなります。
もし、
「こういうケースでも起きた」
「このパターンでハマった」
などあれば、ぜひ教えてください。
今後の記事で取り上げていきます。