1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace try1
{
    public partial class Form1 : Form
    {
        volatile bool start_a = false;
        volatile bool start_b = false;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (start_a == false)
            {
                button1.Text = "Running";
                start_a = true;
                Thread thread2 = new Thread(new ThreadStart(th1));

                thread2.Start();
            }
            else
            {
                button1.Text = "Click to start";
                start_a = false;
            }

        }

        void th1()
        {
         int a=0;
         while (start_a==true)
         {

             label1.Invoke((MethodInvoker)(() => label1.Text = Convert.ToString(a)));
             Thread.Sleep(50);
             a++;
         }



        }

        void th2()
        {
            int b = 0;
            while (start_b == true)
            {
                label2.Invoke((MethodInvoker)(() => label2.Text = Convert.ToString(b)));
                Thread.Sleep(5000);
                b=b+5;
            }



        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (start_b == false)
            {
                button2.Text = "Running";
                start_b = true;
                Thread thread2 = new Thread(new ThreadStart(th2));

                thread2.Start();
            }
            else
            {
                button2.Text = "Click to start";
                start_b = false;
            }
        }

        private void quitting(object sender, FormClosingEventArgs e)
        {
            start_a = false;
            start_b = false;
        }


    }
}
4

3 に答える 3

0

終了する他のスレッドと同期する必要があるため、簡単な解決策はありませんが、Invokeは、他のスレッドを閉じることになっているUIスレッドで実行するように要求します。したがって、tUIはt1、t2に終了を要求しますが、t1、t2は終了するためにtUIを必要とする場合があります。:)

次のようなメソッドApplication.DoEvents();に(読み取り=すべての呼び出し要求を処理する)を追加します。quitting

    private void quitting(object sender, FormClosingEventArgs e)
    {
        start_a = false;
        start_b = false;

        Application.DoEvents(); // NOT the solution, is not enough!!!
    }

ほとんどの競合状態をソートしますが、十分ではありません。

なんで?この可能性はありますが、非常にありそうもない競合状態のため、次のようになります。

t1 before queuing Invoke
                   ~~~~~~~>
                           start_a = false; start_b= false; Application.DoEvents();
                   <~~~~~~~
t1 queue an Invoke
                   ~~~~~~~> (very improbable but possible)
                           (continue trough disposing)
                   <~~~~~~~
queued Invoke on disposed label -> crash!

開始変数のステータスをチェックするクリティカルセクションをロックし、メッセージキューを空にすることでうまくいくはずです。あなたの運動:他の可能な競合状態を見つけ、最悪の場合5秒より早く終了する方法を見つけてください(ヒント:睡眠を使用しないでください。睡眠は悪魔です)。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        object _closing1;
        object _closing2;
        volatile bool start_a = false;
        volatile bool start_b = false;

        public Form1()
        {
            InitializeComponent();

            button1.Text = "Click to start";
            button2.Text = "Click to start";

            _closing1 = new object();
            _closing2 = new object();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (start_a == false)
            {
                button1.Text = "Running";

                start_a = true;

                Thread thread2 = new Thread(new ThreadStart(th1));
                thread2.Start();
            }
            else
            {
                button1.Text = "Click to start";

                start_a = false;
            }

        }

        void th1()
        {
            int a = 0;
            while (true)
            {
                lock (_closing1)
                {
                    if (start_a == false)
                        break;
                    label1.BeginInvoke((MethodInvoker)(() => label1.Text = Convert.ToString(a)));
                }
                Thread.Sleep(50);
                a++;
            }
        }

        void th2()
        {
            int b = 0;

            while (true)
            {
                lock (_closing2)
                {
                    if (start_b == false)
                        break;
                    label2.BeginInvoke((MethodInvoker)(() => label2.Text = Convert.ToString(b)));
                }
                Thread.Sleep(5000);
                b = b + 5;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (start_b == false)
            {
                button2.Text = "Running";
                start_b = true;
                Thread thread2 = new Thread(new ThreadStart(th2));

                thread2.Start();
            }
            else
            {
                button2.Text = "Click to start";
                start_b = false;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            lock (_closing1)
            {
                start_a = false;

                // Clear the message queue now so access on disposed lables is possible.
                // No more invokes will be queued because 1) start_a = false
                // 2) t1 is out of the critical section
                Application.DoEvents();
            }

            lock (_closing2)
            {
                start_b = false;

                // Clear the message queue now so access on disposed lables is possible.
                // No more invokes will be queued because 1) start_b = false
                // 2) t2 is out of the critical section
                Application.DoEvents();
            }
        }
    }
}
于 2011-07-09T02:33:47.203 に答える