23829


お世話になります。

表題の内容では、ほとんど意味が解らないと思います。  
Form1,A,B,C,D,E,Formlessという7つのフォームがあり、Form1はただ単にAを  
ShowDialogで開くだけ、AはBとDを、BはCを、CはFormlessを、DはCとEを、  
EとFormlessは末端の子供として、それぞれがShowDialogで開くという、  
親子関係のプログラムです。

Form1以外のフォームに、フォームが開かれた後、自動で閉じるか子を開くかという  
コードになっています。その流れをUFormという基本クラスで、Activatedとtimer_Tickを  
使用して実装しています。Formlessまで達したときに、カウントを取り、  
Aのフォームでそのカウントされた値を見て、一定値以上に達していれば処理を止めると  
いった感じです。

さて、問題は無事にカウントが一定以上にたまった時です。Aのフォームでカウントを  
チェックしている以上、Dialogで表示している全ての子のフォームが閉じないとAのカウント  
チェックには到達しないと思うのですが、カウントに達した処理が発生した後も、  
Bのフォームだけが開いたままになっています。これが何故なのか解りません。  
AからEまで、構造は若干の違いがありますが、大きな変化はありません。  
決まって毎回Bが開くというのが不可解です。

原因と対策をお教えいただきたいと思います。

下記に、全ソースを記述します(デザイン部分のDesigner.csは省略します)。  
timerのintervalは1にしてあります。  
何卒よろしくお願いいたします。

* * *
[code]

    UForm　すべてのフォームで継承するクラス
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace FormTest2
    {
        public partial class UForm : Form
        {
    
            public UForm()
            {
                InitializeComponent();
    
                this.ClientSize = new Size(640,480);
    
            }
    
            protected virtual void action(string command)
            {
                MessageBox.Show(command);
            }
            public int ID
            {
                get; set;
            }
    
    
            private void UForm_HelpButtonClicked(object sender, System.ComponentModel.CancelEventArgs e)
            {
                this.help();
                e.Cancel = true;
            }
            public virtual void help()
            {
    
                MessageBox.Show("ヘルプが押されました。");
            }
    
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                this.timer1.Enabled = false;
    
                this.autoexec();
            }
    
            private void UForm_Activated(object sender, EventArgs e)
            {
                if (Form1.auto)
                {
                    this.timer1.Enabled = true;
                }
            }
    
            protected virtual void autoexec()
            {
    
            }
    
        }
    }
    
    Form1.cs(起動のメインフォーム。ここから始まります。)
    
    using System;
    using System.Windows.Forms;
    
    namespace FormTest2
    {
        public partial class Form1 : Form
        {
            public static bool auto = true;
            public static int count = 0;
            public static bool flg = true;
    
            private readonly A a = new A();
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                count = 0;
                a.ShowDialog(this);
    
                auto = false;
    
                MessageBox.Show(count + "回です。");
            }
        }
    }
    
    A.cs
    
    using System;
    
    namespace FormTest2
    {
        public class A : UForm
        {
            private B b = new B();
            private D d = new D();
    
            private System.Windows.Forms.Button btnB;
            private System.Windows.Forms.Button btnD;
            public A()
            {
                InitializeComponent();
                this.ClientSize = new System.Drawing.Size(580, 395);
            }
    
    
            protected override void autoexec()
            {
                int i = new Random().Next(2);
    
                this.action("" + i);
            }
    
            protected override void action(string value)
            {
                string st = value;
    
                if (st == "0")
                {
                    b.ShowDialog(this);
                }
                else
                {
                    d.ShowDialog(this);
                }
    
                if (Form1.count >= 100)
                {
                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                    this.Close();
                }
            }
    
            private void InitializeComponent()
            {
                this.btnB = new System.Windows.Forms.Button();
                this.btnD = new System.Windows.Forms.Button();
                this.SuspendLayout();
                // 
                // btnB
                // 
                this.btnB.Location = new System.Drawing.Point(18, 22);
                this.btnB.Name = "btnB";
                this.btnB.Size = new System.Drawing.Size(138, 55);
                this.btnB.TabIndex = 7;
                this.btnB.Text = "B";
                this.btnB.UseVisualStyleBackColor = true;
                // 
                // btnD
                // 
                this.btnD.Location = new System.Drawing.Point(18, 83);
                this.btnD.Name = "btnD";
                this.btnD.Size = new System.Drawing.Size(138, 55);
                this.btnD.TabIndex = 8;
                this.btnD.Text = "D";
                this.btnD.UseVisualStyleBackColor = true;
                // 
                // A
                // 
                this.ClientSize = new System.Drawing.Size(640, 480);
                this.Controls.Add(this.btnD);
                this.Controls.Add(this.btnB);
                this.Name = "A";
                this.Text = "A";
                this.Controls.SetChildIndex(this.btnExit, 0);
                this.Controls.SetChildIndex(this.btnB, 0);
                this.Controls.SetChildIndex(this.btnD, 0);
                this.ResumeLayout(false);
    
            }
        }
    }
    
    B.cs
    
    using System;
    
    namespace FormTest2
    {
        public class B : UForm
        {
            private C f = new C();
    
            public B()
            {
                InitializeComponent();
            }
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // B
                // 
                this.ClientSize = new System.Drawing.Size(424, 267);
                this.Name = "B";
                this.Text = "B";
                this.ResumeLayout(false);
    
            }
    
            protected override void autoexec()
            {
                int i = new Random().Next(3);
                this.action("" +i);
            }
    
            protected override void action(string value)
            {
                string st = value;
                if (st == "0")
                {
                    this.Close();
                }
                else
                {
                    f.ShowDialog(this);
                }
            }
        }
    }
    
    C.cs
    
    using System;
    
    namespace FormTest2
    {
        public class C : UForm
        {
            private Formless f = new Formless();
            public C()
            {
                InitializeComponent();
            }
    
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // C
                // 
                this.ClientSize = new System.Drawing.Size(239, 226);
                this.Name = "C";
                this.Text = "C";
                this.ResumeLayout(false);
            }
    
            protected override void autoexec()
            {
                int i = new Random().Next(4);
                this.action("" + i);
            }
    
            protected override void action(string value)
            {
                string st = value;
                if (st == "0")
                {
                    this.Close();
                }
                else
                {
                    f.ShowDialog(this);
                }
            }
        }
    }
    
    D.cs
    
    using System;
    
    namespace FormTest2
    {
        public class D : UForm
        {
            private E e = new E();
            private C c = new C();
    
            public D()
            {
                InitializeComponent();
            }
    
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // D
                // 
                this.BackColor = System.Drawing.Color.Red;
                this.ClientSize = new System.Drawing.Size(473, 408);
                this.Name = "D";
                this.Text = "D";
                this.ResumeLayout(false);
    
            }
            protected override void autoexec()
            {
                int i = new Random().Next(3);
                this.action("" + i);
            }
            protected override void action(string value)
            {
                string st = value;
    
                if (st == "0")
                {
                    this.Close();
                }
                else if(st == "1")
                {
                    e.ShowDialog(this);
                }
                else
                {
                    c.ShowDialog(this);
                }
            }
        }
    }
    
    E.cs
    
    namespace FormTest2
    {
        public class E : UForm
        {
            public E()
            {
                InitializeComponent();
            }
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // E
                // 
                this.BackColor = System.Drawing.Color.Olive;
                this.ClientSize = new System.Drawing.Size(823, 164);
                this.Name = "E";
                this.Text = "E";
                this.ResumeLayout(false);
    
            }
    
            protected override void autoexec()
            {
                this.action("");
    
                this.btnExit.PerformClick();
                this.Close();
            }
    
            protected override void action(string value)
            { 
            }
        }
    }
    
    Formless.cs
    
    namespace FormTest2
    {
        public class Formless : UForm
        {
            private System.ComponentModel.IContainer components;
    
            public Formless()
            {
                InitializeComponent();
            }
    
            private void InitializeComponent()
            {
                this.SuspendLayout();
                // 
                // Formless
                // 
                this.BackColor = System.Drawing.Color.Red;
                this.ClientSize = new System.Drawing.Size(282, 253);
                this.ControlBox = false;
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                this.Name = "Formless";
                this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
                this.ResumeLayout(false);
    
            }
    
            protected override void autoexec()
            {
                this.action("");
            }
    
            protected override void action(string value)
            { 
                Form1.count++;
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2016-04-07T06:29:07.883
23816
2016-04-07T14:22:40.730
2016-04-07T14:22:40.730
8000
9374
question
c# winforms
C# フォームを連続で開閉を繰り返した結果、中途半端にフォームが残る


フォームAとBだけにして、`UForm.timer1_Tick` と `UForm.OnClosed` で記録を取ると・・・

[code]

    A tick
    B tick
    B closed
    A closed
    A tick
    B closed
    A closed
    
[/code]

何故かAがクローズされた後にAのTickが呼ばれ、Bの表示とAのクローズが行われていますね。

流れとしてはこうです。

  1. （カウントが一定数を超えた状態で）BまたはDが閉じられる
  2. **ここでAがアクティブになったことでUForm_Activatedが呼ばれる** 。  
この時点ではまだautoはtrueなのでタイマーが再開される。

  3. Aから呼び出したShowDialogが完了し、autoをfalseにし、Aを閉じる
  4. 上で再開されたタイマーが `MessageBox.Show()` と前後して処理され、BまたはDが表示される

ということのようでした。

手っ取り早い対策としては、ShowDialogが完了した時点でautoをfalseにするだけでなく、タイマーを手動で停止するとよいのではないでしょうか。

参考までに、冒頭の記録を取った際のコードを載せておきます。

[code]

    using System;
    using System.Diagnostics;
    using System.Windows.Forms;
    
    class Program
    {
        private static void Main(string[] args)
        {
            Application.Run(new Form1());
        }
    }
    
    public class UForm : Form
    {
        public Timer timer1 = new Timer();
    
        public UForm()
        {
            timer1.Tick += timer1_Tick;
            this.Activated += UForm_Activated;
        }
    
        private void timer1_Tick(object sender, EventArgs e)
        {
            this.timer1.Enabled = false;
            Debug.WriteLine(this.GetType().Name + " tick");
            this.autoexec();
        }
    
        private void UForm_Activated(object sender, EventArgs e)
        {
            Debug.WriteLine(this.GetType().Name + " activated");
            if (Form1.auto)
            {
                this.timer1.Enabled = true;
            }
        }
    
        protected virtual void autoexec()
        {
        }
    
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            Debug.WriteLine(this.GetType().Name + " closed");
        }
    }
    
    public partial class Form1 : Form
    {
        public static bool auto = true;
    
        private readonly A a = new A();
    
        public Form1()
        {
            var button1 = new Button();
            button1.Click += button1_Click;
            this.Controls.Add(button1);
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            new A().ShowDialog(this);
            auto = false;
    
            MessageBox.Show("おわり");
        }
    }
    
    public class A : UForm
    {
        protected override void autoexec()
        {
            new B().ShowDialog(this);
            this.Close();
        }
    }
    
    public class B : UForm
    {
        protected override void autoexec()
        {
            this.Close();
        }
    }
    
[/code]


CC BY-SA 3.0
2016-04-07T14:22:15.770
23829
2016-04-07T14:22:15.770
8000
23816
answer