关闭表单后杀死一个帖子?

时间:2014-01-13 11:15:16

标签: c# multithreading

我有一个在打开新表单实例时创建的线程。 此表单打开时,此线程应始终运行。 表单关闭后,它应该死掉。

问题是当我打开同一表单的新实例时,它使用相同的线程。

我正在寻找的正确代码可能就像我在想的那样......除非这是无效的:

t = new Task(Task.Factory.StartNew(() => totalDistance()));

以下是整个代码: WindowsFormClosing的方法可能是不必要的,但我没有想法。

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

    namespace ITS3_Eksamen_F2014_201270810
    {
    public partial class DistanceForm : Form
    {
        Data dat;
        private string name;
        Task t;
        private bool killThread;

        public DistanceForm(Data d, string n)
        {
            dat = d;
            name = n;
            InitializeComponent();
            getDistance(name);
            nameLabel.Text = name;
            t = Task.Factory.StartNew(() => totalDistance());
            killThread = false;
        }

        private void getDistance(string name)
        {
            var dList = new List<Distance>();
            dList = dat.getDistance(name);
            int i = 0;
            dataGridView1.Rows.Clear();
            foreach (Distance dist in dList)
            {
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = dist.getTid();
                dataGridView1.Rows[i].Cells[1].Value = dist.getAngivelse();
                dataGridView1.Rows[i].Cells[2].Value = dist.getLængde();
                dataGridView1.Rows[i].Cells[3].Value = dat.getFullName(dist.getInitialer());
                i++;
            }
        }

        private void updateInitials(string initialer, int rowNumber)
        {
            dataGridView1.Rows[rowNumber].Cells[3].Value = dat.getFullName(initialer);
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            int rowNumber = dataGridView1.CurrentCell.RowIndex;

            if (!dataGridView1.Rows[rowNumber].Cells[0].Value.ToString().Equals("") 
                && !dataGridView1.Rows[rowNumber].Cells[1].Value.ToString().Equals("") 
                && !dataGridView1.Rows[rowNumber].Cells[2].Value.ToString().Equals("")
                && !dataGridView1.Rows[rowNumber].Cells[3].Value.ToString().Equals(""))
            {
                var tid = dataGridView1.Rows[rowNumber].Cells[0].Value.ToString();
                var længde = dataGridView1.Rows[rowNumber].Cells[1].Value.ToString();
                var angivelse = dataGridView1.Rows[rowNumber].Cells[2].Value.ToString();
                var initialer = dataGridView1.Rows[rowNumber].Cells[3].Value.ToString();
                dat.addDistance(name, tid, længde, angivelse, initialer);
            }
            else
            {
                MessageBox.Show("Du skal udfylde alle felter!");
            }
            int currentRow = dataGridView1.CurrentCell.RowIndex;
            string currentRowInitialer = dataGridView1.Rows[currentRow].Cells[3].Value.ToString();
            updateInitials(currentRowInitialer, currentRow);
        }

        private void buttonRemove_Click(object sender, EventArgs e)
        {
            int number = dataGridView1.CurrentCell.RowIndex;
            dat.deleteDistance(name, number);
        }

        private void totalDistance()
        {
            while (killThread == false)
            {
                int totalDist = 0;
                int newDist = 0;
                var testList = dat.getDistance(name);
                foreach (Distance dist in testList)
                {
                    newDist = Convert.ToInt32(dist.getLængde().Replace(" km", ""));
                    totalDist = totalDist + newDist;
                }

                this.BeginInvoke((Action)(() =>
                    {
                        textBox1.Text = Convert.ToString(totalDist) + " km";
                    }));
            }
        }

        private void WindowsFormClosing(object sender, FormClosingEventArgs e)
        {
            killThread = true;
        }
    }
}

提前致谢!

1 个答案:

答案 0 :(得分:7)

你可以用这个:

private Thread _thread;

public DistanceForm()
{
    InitializeComponent();

    _thread = new Thread(new ThreadStart(totalDistance));
    _thread.Start();
}

public void FormClosed(object sender, EventArgs e)
{
    killThread = true;
    _thread.Join();
}

我建议不要使用布尔值,而是建议使用ManualResetEvent。

喜欢:

private Thread _thread;
private ManualResetEvent _started = new ManualResetEvent(false);
private ManualResetEvent _terminating = new ManualResetEvent(false);
private ManualResetEvent _terminated = new ManualResetEvent(false);

public void InitializeComponent()
{
    _thread = new Thread(() => totalDistance());
    _thread.Start();

    // wait until the thread is started.
    _started.WaitOne();
}

private void totalDistance()
{
    // do some initialization stuff..

    // Set started.
    _started.Set();
    while(!_terminating.WaitOne(0))
    {
        // ...
    }
    _terminated.Set();
}

public void FormClosed(object sender, EventArgs e)
{
    // request for terminating.
    _terminating.Set();
    // wait until it's terminated.
    _terminated.WaitOne();
}

started在这种情况下并不相关,但是当我使用线程(如客户端等)构建一些实例时,我会正常使用它。

该示例无异常处理。你应该添加try / finally。

这样你就可以完全控制线程上的作业,布尔检查是线程安全

整个事物可以包裹在一个新对象中。 :)