用心计较般般错 安心自守事事宽

cgl 坚持、努力终有所获
  新随笔  :: 管理

线程的终止和继续

Posted on 2013-03-29 15:00  用心计较般般错 安心自守事事宽  阅读(197)  评论(0编辑  收藏  举报

  问题:单击一个按钮,让线程运行,做一个50000之内的数循环,让一个TextBox显示每一个当前的循环数字。当线程正在运行时,如果第二次或者多次单击按钮,让线程重头开始运行。怎么办?,经过几次试验,代码如下:

  线程只有一个在运行,不会产生多个线程,因为线程是再Abort()后,重新新的线程的。

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 WindowsFormsApplication18
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            _ThreadCur = new Thread(new ThreadStart(RunPic));
        }

        /// <summary>
        /// 主线程
        /// </summary>
        Thread _ThreadCur = null;
        private void btStart_Click(object sender, EventArgs e)
        {
            //判断线程是否活动,如果活动,终止线程
            if (_ThreadCur.IsAlive == true)
            {
                //线程终止
                _ThreadCur.Abort();
            }
            //如果线程状态没有开始,那么开始线程
            if (_ThreadCur.ThreadState == ThreadState.Unstarted)
            {
                _ThreadCur.Start();
            }
            //如果线程停止了,需要重建线程,然后开始。终止的线程不能启动
            if (_ThreadCur.ThreadState == ThreadState.Stopped)
            {
                _ThreadCur = new Thread(new ThreadStart(RunPic));
                _ThreadCur.Start();
            }
        }
        public void RunPic()
        {
            for (int i = 0; i < 500; i++)
            {
                if (this.txtShowNum.InvokeRequired)
                {
                    
                    this.Invoke(new setLabHandle(setLabeText), new object[] { i.ToString() });
                }
                else
                {
                    setLabeText(i.ToString());
                }
                Thread.Sleep(10);
            }
        }
        public delegate void setLabHandle(string pText);
        private void setLabeText(string pText)
        {
            this.txtShowNum.Text = pText;
        }

    }

程序实现了上述功能,但是问题出在,当线程没有运行完毕时,如果关闭窗体,则系统报错,错误内容为

:“无法访问已释放的对象。”

如图所示:

解决办法有两种:

(1)在this.Invoke出,把Invoke替换为BeginInvoke

代码如下:

        public void RunPic()
        {
            for (int i = 0; i < 500; i++)
            {
                if (this.txtShowNum.InvokeRequired)
                {
                    
                    //this.Invoke(new setLabHandle(setLabeText), new object[] { i.ToString() });
                    //把Invoke替换为BeginInvoke
                    this.BeginInvoke(new setLabHandle(setLabeText), new object[] { i.ToString() });
                }
                else
                {
                    setLabeText(i.ToString());
                }
                Thread.Sleep(10);
            }
        }

Invoke与BeginInvoke的区别

(2)在关闭窗体事件中,判断_ThreadCur是否活动,如果活动,那么终止,代码如下:

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (_ThreadCur != null && _ThreadCur.IsAlive)
            {
                _ThreadCur.Abort();
            }
        }