C#多线程(二) -- ThreadStart

ThreadStart 方式实现多线程

先以一个例子体现一下多线程带来的好处,首先在Message类中建立一个方法ShowMessage(),里面显示了当前运行线程的Id,并使用Thread.Sleep(int ) 方法模拟部分工作。在main()中通过ThreadStart委托绑定Message对象的ShowMessage() 方法,然后通过Thread.Start() 执行异步方法

namespace Thread1
{
    public class Message
    {
        public void ShowMessage()
        {
            string message = string.Format("Async threadId is :{0}", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(message);

            for (int n = 0; n < 100; n++)
            {
                Thread.Sleep(300);
                Console.WriteLine("The number is:" + n.ToString());
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main threadId is:" + Thread.CurrentThread.ManagedThreadId);
            Message message = new Message();
            Thread thread = new Thread(new ThreadStart(message.ShowMessage));
            thread.Start();
            Console.WriteLine("Do something ..........!");
            Console.WriteLine("Main thread working is complete!");
        }
    }
}

请注意运行结果,在调用Thread.Start()方法后,系统以异步方式运行Message.ShowMessage(),而主线程的操作是继续执行的,在Message.ShowMessage()完成前,主线程已完成所有的操作

这里写图片描述

用 ParameterizedThreadStart 委托

ParameterizedThreadStart委托与ThreadStart委托非常相似,但ParameterizedThreadStart委托是面向带参数方法的。(eg:thread.Start(person)) 注意ParameterizedThreadStart 对应方法的参数为object,此参数可以为一个值对象,也可以为一个自定义对象

namespace Thread2
{
    public class Person
    {
        public string Name
        {
            get;
            set;
        }
        public int Age
       {
            get;
            set;
        }
    }

    public class Message
    {
        public void ShowMessage(object person)
        {
            if (person != null)
            {
                Person _person = (Person)person;
                string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}",
                    _person.Name, _person.Age, Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine(message);
            }
            for (int n = 0; n < 10; n++)
            {
                Thread.Sleep(300);
                Console.WriteLine("The number is:" + n.ToString());
            }
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main threadId is:" + Thread.CurrentThread.ManagedThreadId);

            Message message = new Message();
            //绑定带参数的异步方法
            Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage));
            Person person = new Person();
            person.Name = "Jack";
            person.Age = 21;
            thread.Start(person);  //启动异步线程 

            Console.WriteLine("Do something ..........!");
            Console.WriteLine("Main thread working is complete!");

        }
    }
}

这里写图片描述

前台线程与后台线程

注意以上两个例子都没有使用Console.ReadKey(),但系统依然会等待异步线程完成后才会结束。这是因为使用Thread.Start()启动的线程默认为前台线程,而系统必须等待所有前台线程运行结束后,应用程序域才会自动卸载

Thread有一个属性IsBackground,通过把此属性设置为true,就可以把线程设置为后台线程!这时应用程序域将在主线程完成时就被卸载,而不会等待异步线程的运行

挂起线程

namespace Thread3
{
    public class Message
    {
        public void ShowMessage()
        {
            string message = string.Format("\nAsync threadId is:{0}",
                                           Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(message);
            for (int n = 0; n < 10; n++)
            {
                Thread.Sleep(300);
                Console.WriteLine("The number is:" + n.ToString());
            }
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main threadId is:" + Thread.CurrentThread.ManagedThreadId);

            Message message = new Message();
            Thread thread = new Thread(new ThreadStart(message.ShowMessage));
            thread.IsBackground = true;
            thread.Start();

            Console.WriteLine("Do something ..........!");
            Console.WriteLine("Main thread working is complete!");
            Console.WriteLine("Main thread sleep!");
            Thread.Sleep(500);
        }
    }
}

这里写图片描述

系统无法预知异步线程需要运行的时间,所以用通过Thread.Sleep(int)阻塞主线程并不是一个好的解决方法。有见及此,.NET专门为等待异步线程完成开发了另一个方法thread.Join()。把上面例子中的最后一行Thread.Sleep(500)修改为 thread.Join() 就能保证主线程在异步线程thread运行结束后才会终止

Suspend 与 Resume (慎用)

Thread.Suspend()与 Thread.Resume()是在Framework1.0 就已经存在的老方法了,它们分别可以挂起、恢复线程。但在Framework2.0中就已经明确排斥这两个方法。这是因为一旦某个线程占用了已有的资源,再使用Suspend()使线程长期处于挂起状态,当在其他线程调用这些资源的时候就会引起死锁!所以在没有必要的情况下应该避免使用这两个方法

终止线程

若想终止正在运行的线程,可以使用Abort()方法。在使用Abort()的时候,将引发一个特殊异常 ThreadAbortException

若想在线程终止前恢复线程的执行,可以在捕获异常后 ,在catch(ThreadAbortException ex){…} 中调用Thread.ResetAbort()取消终止

而使用Thread.Join()可以保证应用程序域等待异步线程结束后才终止运行

namespace Thread4
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main threadId is:" +
                              Thread.CurrentThread.ManagedThreadId);

            Thread thread = new Thread(new ThreadStart(AsyncThread));
            thread.IsBackground = true;
            thread.Start();
            thread.Join();

        }

        //以异步方式调用
        static void AsyncThread()
        {
            try
            {
                string message = string.Format("\nAsync threadId is:{0}",
                   Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine(message);

                for (int n = 0; n < 10; n++)
                {
                    //当n等于4时,终止线程
                    if (n >= 4)
                    {
                        Thread.CurrentThread.Abort(n);
                    }
                    Thread.Sleep(300);
                    Console.WriteLine("The number is:" + n.ToString());
                }
            }
            catch (ThreadAbortException ex)
            {
                //输出终止线程时n的值
                if (ex.ExceptionState != null)
                    Console.WriteLine(string.Format("Thread abort when the number is: {0}!",
                                                     ex.ExceptionState.ToString()));

                //取消终止,继续执行线程
                Thread.ResetAbort();
                Console.WriteLine("Thread ResetAbort!");
            }

            //线程结束
            Console.WriteLine("Thread Close!");
            Thread.Sleep(50000);
        }
    }
}

这里写图片描述

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值