
実現したいこと
MessageBoxが表示される前に次のメッセージボックスを表示しようとすると、最後のMessageBoxしか表示されません。
モーダルのFormであれば表示されます。
なお実際に表示されるまでThread.Sleep(1)などで待てば表示されますが、
スリープ時間が短いと何個か表示されない時があります。
以下はそれぞれ5つのモーダルダイアログを表示するサンプルコードです。
Thread.Sleep(1000)などかなり余裕のある時間にするかMessageBoxをFormで自作すると回避可能ですが、
この現象に知見があれば回答をお願いします。
該当のソースコード
//最後のダイアログしか表示されない。 private void button1_Click(object sender, EventArgs e){ Task.Run(() => { for (int i = 0; i < 5; i++){ int a = i; BeginInvoke((MethodInvoker)(() => { MessageBox.Show(this, a + ""); })); }; }); } //MessageBoxではなくFormなら表示できる。 private void button2_Click(object sender, EventArgs e){ Task.Run(() => { for (int i = 0; i < 5; i++){ int a = i; BeginInvoke((MethodInvoker)(() => { var form = new Form(); form.Text = a + ""; form.ShowDialog(); })); }; }); } //BeginInvokeの前にスリープを入れるとすべて表示されるが、スリープ時間が短いと何個か表示されない時がある。 private void button3_Click(object sender, EventArgs e){ Task.Run(() => { for (int i = 0; i < 5; i++){ Thread.Sleep(1); int a = i; BeginInvoke((MethodInvoker)(() => { MessageBox.Show(this, a + ""); })); }; }); }
補足情報(FW/ツールのバージョンなど)
.NET Framwork 4.8 Windows Formsアプリケーション

あなたの言う「モーダル」って何なのでしょう? 普通モーダルと言うと複数開くものではないはずですけど。
親ウィンドウを操作できなくする子ウィンドウです。普通に複数開けるものだと思っていました。

> 親ウィンドウを操作できなくする子ウィンドウ
であれば、複数開いたりするものではないと思いますけど。また、UI スレッドではないスレッドプールスレッド(メッセージループを持たない)で MessageBox.Show するというのは、どういう意図があるのでしょうか?
そもそも何がしたいのですか? XY 問題のような気がしますけど。
XY 問題とは、X という課題があって、Y という解決策を考えついて Y について質問したが(質問には X は書かないで)、Y は X の解決策とはなっておらず、回答者と質問者間で話がかみ合わず、一向に解決にならないということです。
BeginInvokeによりUI スレッドでMessageBox.Showをしています。
課題はこの現象に知見のある方へ解決方法があるか質問させていただいております。
https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/MessageBox.cs
のソースを読みましたが、表示処理はuser32.dllのMessageBoxのと同じっぽいですし、user32.dllのMessageBoxでも同様の現象となりました。SurferOnWwwさんの言う通り、Microsoft社はそもそも複数開くことを想定していないのかもしれないですね。
> 親ウィンドウを操作できなくする子ウィンドウです。
「閉じるまで(親に限らず)他のウィンドウ操作できないウィンドウ」じゃなくて?
そうであるなら複数開ける意味はなくなるかと。
モーダルウィンドウはユーザーに最優先で決済してほしいものを提示するもので複数開くものではありませんが、どこかでそんな UI を見たんでしょうか?
何に便利なんですかそれ?
すでに存在するシステムでそのような仕様があり不備を修正したいだけです。
「そのような仕様」と「不備」と「修正」の意味がわかりません。
モーダルダイアログを一つだけ開くと言うのは不備でもなんでもないですが、何を不備と言っていますか?

> すでに存在するシステムでそのような仕様があり不備を修正したいだけです。
MessageBox を同時に複数開くことが「不備」です。「不備を修正したい」ならそこを修正するのが筋では?
タイミングによって複数のモーダルダイアログがネストされて表示される場合と最後のものだけ表示される場合があり不定であることを不備と表現しました。
MessageBox を同時に複数開くことが「不備」という発想はありませんでしたが、解決方法が無さそうななので1つづつ開くように改修予定です。

> タイミングによって複数のモーダルダイアログがネストされて表示される場合と最後のものだけ表示される場合があり不定であることを不備と表現しました。
そういうのは不備とは言いません。そもそもMessageBox を複数開くことはあり得ないのだから。
強いて言うならあなたの考えの不備です。そこをいろいろ言われて取り繕うのは止めましょう。指摘されたら素直に認めてあなたの考えを修正してください。でないと話をしても時間の無駄になります。
よろしければ、「MessageBox を複数開くことはあり得ない」とおっしゃれられる根拠がございましたら、教えて頂けますでしょうか。
モーダルダイアログを開き、そこから別のモーダルダイアログを開くようにネストしたいのであれば、ダイアログ自体を自分で設計するのが普通のやり方です。
一つのウィンドウから複数のモーダルダイアログを開くような特殊な UI はユーザーも戸惑うでしょう。
> よろしければ、「MessageBox を複数開くことはあり得ない」とおっしゃれられる根拠がございましたら、教えて頂けますでしょうか。
メッセージボックスはユーザーに最優先で伝えたいことを伝え、それを確実に伝えたことを確認して次の処理に移るための UI です。
複数のメッセージを表示したいだけならトーストを使いましょう。
ありがとうございました。本質問は解決とさせていただきます。

回答1件
あなたの回答
tips
プレビュー