22558


お世話になります。

ミニゲームを作ろうとしています。  
簡単な勝ち負けのフォームを繰り返すだけの処理なんですが、  
それを自動化しようと、『フォームがアクティブ化されたらボタンを押される』  
のような処理でテストしていたら、図の様なエラーが発生しました。  
[![画像の説明をここに入力](https://i.stack.imgur.com/G87d5.png)](https://i.stack.imgur.com/G87d5.png)

30回ほど繰り返すと発生するみたいですが、performClickを外して、  
手動で行っている分には発生しません。

対策方法を教えてください。

下記に、全ソースを記述します。

[code]

    using System;
    using System.Windows.Forms;
    
    namespace Formest
    {
        public partial class Form1 : Form
        {
    　　　　/**　フォーム1　ただフォーム2をボタンで表示するだけ　*/
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Form2 f2 = new Form2();
                f2.ShowDialog(this);
            }
        }
    }
    
    using System;
    using System.Windows.Forms;
    
    namespace Formest
    {
        /** フォーム3を呼び出す為のフォーム。ここで自動化を行っている。 */
        public partial class Form2 : Form
        {
            private const int WIN = 1;
            private const int LOSE = -1;
    
            private Form3 f3 = new Form3();
    
            private int win = 0;
    
            public Form2()
            {
                InitializeComponent();
            }
    
            private void Form2_Activated(object sender, EventArgs e)
            {
                this.Text = "" + this.win;
    
                // ↓自動化している。コメントアウトして手動でカチカチすれば正しく動く。
                this.button1.PerformClick();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                this.Hide();
    
                if (this.process() == LOSE)
                {
                    this.Show();
                    MessageBox.Show("残念。" + this.win + "連勝まで行きました。");
                    this.Close();
                }
                else
                {
                    this.Show();
                    this.Activate();
                }
            }
            private int process()
            {
                //  ここで例外発生
                DialogResult ans = this.f3.ShowDialog(this);
    
    
                // 勝った場合
                if (ans == DialogResult.Yes)
                {
                    this.win++;
    
                    return WIN;
                }
    
                //  負けた場合
                else if (ans == DialogResult.No)
                {
                    return LOSE;
                }
                return 0;
            }
        }
    }
    
    
    using System;
    using System.Windows.Forms;
    
    namespace Formest
    {
        public partial class Form3 : Form
        {
    　　　　/* 仮の戦闘シーン。今は乱数で勝敗を分けているだけ。 */
            public Form3()
            {
                InitializeComponent();
            }
    
            private void Form3_Shown(object sender, EventArgs e)
            {
                System.Threading.Thread.Sleep(50);
    
                Random rnd = new Random();
    
                int i = rnd.Next(256);
    
                if (i == 0)
                {
                    this.DialogResult = DialogResult.No;
    
                }
                else
                {
                    this.DialogResult = DialogResult.Yes;
                }
            }
        }
    }
    
[/code]

以上です。  
Form2にあるボタンをクリックすれば戦闘が始まる感じです。

よろしくお願いいたします。


CC BY-SA 3.0
2016-02-26T04:16:12.113
22554
2016-02-26T06:07:34.240
2016-02-26T06:07:34.240
8000
9374
question
c# winforms
C# 同じフォームの表示、非表示を繰り返すと発生する例外の回避の仕方


`HResult`が`0x80004005`(`E_FAIL`)のため断言はできませんが、おそらく同期的にイベントを処理しすぎで何らかのリソースが不足しているのではないでしょうか。

とりあえず、Form2の`Button.Click`と`Form.Activated`を切り離したら例外が発生しないようです。

[code]

    private void button1_Click(object sender, EventArgs e)
    {
        this.Hide();
    
        if (this.process() == LOSE)
        {
            this.Show();
            MessageBox.Show("残念。" + this.win + "連勝まで行きました。");
            this.Close();
        }
        else
        {
            this.Show();
    
            // Activate()のかわりに非同期処理を行う
            Task.Delay(50).ContinueWith(t =>
            {
                this.Text = "" + this.win;
                this.button1.PerformClick();
    
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
    }
    
[/code]


CC BY-SA 3.0
2016-02-26T05:06:00.000
22558
2016-02-26T05:06:00.000
5750
22554
answer


[Form.Activatedイベント](https://msdn.microsoft.com/ja-
jp/library/system.windows.forms.form.activated\(v=vs.110\).aspx)のタイミングを取り違えています。`f3`を表示して閉じた時点でもフォーカスを得、更に`Activate()`メソッドでも得るため、それぞれで`Activated`イベントが発生します。`process()`メソッドの呼び出されている回数を数えると状況がわかるでしょう。

それとは別にフォームのイベントハンドラ内で`Thread.Sleep()`してはいけません。


CC BY-SA 3.0
2016-02-26T05:45:14.807
22562
2016-02-26T05:45:14.807
4236
22554
answer