C#--线程的基本操作

创建线程

在C#中创建线程时,首先需要创建一个ThreadStart委托实例,再以这个ThreadStart委托作为为参数,来构造Thread实例。
注意:Thread类拥有四种重载的构造函数,常用的一个函数接收一个ThreadStart类型的参数,而ThreadStart是一个委托,其语法格式如下:

public delegate void ThreadStart()

线程休眠

线程的休眠是通过Thread类的Sleep方法实现的,而Thread类的实例的IsAlive属性可以判断线程是否执行完毕。Sleep方法有以下两种重载形式。
(1)将当前线程挂起指定的毫秒数,语法格式如下:

public static void Sleep (int millisecondsTimeout)

millisecondsTimeout:线程被阻止的毫秒数。如果该参数的值为零,则该线程会将其时间的剩余部分让给任何已经准备好运行的、具有同等优先级的线程,否则会无限期阻止线程。
(2)将当前线程挂起指定的时间,语法格式如下:

public static void Sleep (TimeSpan timeout)

timeout:线程被阻止的时间量的TimeSpan。
编写程序,创建线程,并在运行时休眠5秒。

using System;
using System.Threading;
namespace Text
{
    class Program
    {
        //下面的实例演示了 sleep() 方法的使用,用于在一个特定的时间暂停线程。
        public static void Method()
        {
            Console.WriteLine("启动线程");
            // 线程暂停 5000 毫秒
            int t = 5000;
            Console.WriteLine("线程暂停 {0} 秒",
                              t / 1000);
            Thread.Sleep(t);
            Console.WriteLine("线程恢复");
        }
        static void Main(string[] args)
        {
            ThreadStart ts = new ThreadStart(Method);
            Thread th = new Thread(ts);//创建线程
            th.Start();  //启动线程
            Console.ReadKey();
        }
    }
}

【程序分析】本例演示了线程的休眠。在代码中,首先用户可以自定义一个静态的void方法Method;然后在Main方法中,创建ThreadStart委托的实例ts;接着通过ts构造Thread类的实例th,这样就创建好一个线程;最后通过Start方法,启动线程,由于在Method方法中调用了Sleep方法,使线程休眠5秒后再运行。

启动线程
线程暂停 5 秒
线程恢复

线程的挂起与恢复

Suspend方法用于挂起线程,Resume方法用于继续执行已经挂起的线程。可以使用这两个方法进行线程的同步,和Start方法有些类似的是,在调用Suspend方法后不会立即停止,而是执行到一个安全点后挂起。

  1. Suspend方法
    挂起线程,或者如果线程已挂起,则不起作用,语法格式如下:
public void Suspend();
  1. Resume方法
    继续已挂起的线程,语法格式如下:
public void Resume();

编写程序,自定义两个线程,主线程(MainThread方法)和工作线程(WorkThread方法),主线程倒序输出,工作线程正序输出。先完成主线程,再完成工作线程。

using System;
using System.Threading;

namespace ThreadExample
{
    class Program
    {
        static void Main(string[] args)
        {
            ThreadStart entry = new ThreadStart(CalcSum);
            Thread workThread = new Thread(entry);
            workThread.Start();
            workThread.Suspend();//挂起线程(改动部分)
            CalcGap();
            workThread.Resume();//恢复线程(改动部分)
            Console.ReadKey();

        }

        static void CalcSum()
        {
          
            for (long i = 0; i < 1000000000; i++)
            {               
                if (i % 100000000 == 0 && i != 0)
                {
                    Console.WriteLine("workThread-->i={0}", i);
                }
            }
        }

        static void CalcGap()
        {
            long gap = 0;
            for (long i = 1000000000; i >= 0; i--)
            {
                gap = i ;
                if (i % 100000000 == 0 && i != 0)
                {
                    Console.WriteLine("MainThread-->i={0}:gap={1}", i, gap);
                }
            }
        }
    }
}

【程序分析】本例演示了线程的挂起与恢复。在代码中,用户定义了两个方法WorkThread和MainThread。MainThread方法用于倒序输出0~10;WorkThread方法用于正序输出1~9;然后在Main方法中,创建ThreadStart委托的实例work;接着通过work构造Thread类的实例th,这样就创建好一个线程;最后通过Start方法,启动线程。挂起线程使用Suspend方法。线程被挂起后,操作被停止或进入休眠状态。因此,从结果中可以看出,此时主线程正常执行,但是工作线程WorkThread没有被执行。那么要想工作线程能继续执行,就需要使用Resume方法恢复线程。

MainThread-->i=1000000000:gap=1000000000
MainThread-->i=900000000:gap=900000000
MainThread-->i=800000000:gap=800000000
MainThread-->i=700000000:gap=700000000
MainThread-->i=600000000:gap=600000000
MainThread-->i=500000000:gap=500000000
MainThread-->i=400000000:gap=400000000
MainThread-->i=300000000:gap=300000000
MainThread-->i=200000000:gap=200000000
MainThread-->i=100000000:gap=100000000
workThread-->i=100000000
workThread-->i=200000000
workThread-->i=300000000
workThread-->i=400000000
workThread-->i=500000000
workThread-->i=600000000
workThread-->i=700000000
workThread-->i=800000000
workThread-->i=900000000

终止线程

线程的终止是通过Thread类的Abort方法和Join方法来实现的。

  1. Abort方法
    当一个线程执行时间太长时,用户有可能要终止这个线程,这就要使用Abort方法。该方法有两种重载方式:
public void Abort() //终止进程
public void Abort(Object stateInfo)

参数stateInfo是一个对象,包含应用程序特定的信息(如状态),该信息可供正被终止的线程使用
注意:在线程调用Abort方法时,会引发ThreadAbortException异常。如果没有捕获异常,线程将会终止通过。
编写程序,启动线程,while循环5次后终止线程。

using System;
using System.Threading;
namespace Project5
{
    class Program
    {
        static void Main(string[] args)
        {
            ThreadStart work = new ThreadStart(WorkThread);   //创建工作线程
            Thread th = new Thread(work);
            th.Start();    //启动线程           
            int i = 0;
            while (th.IsAlive)
            {
                i++;
                Thread.Sleep(500);
                if (i == 5)
                {
                    th.Abort();  //线程被终止
                    Console.WriteLine("\r\n线程被终止");
                }
            }
            Console.ReadKey();
        }
        static void WorkThread()
        {
            for (long i = 0; i < 1000000000; i++)
            {
                if (i % 100000000 == 0 && i != 0)
                {
                    Console.WriteLine("工作线程WorkThread-->i={0}", i);
                }
            }
        }
    }
}

【程序分析】本例演示了线程的终止。在代码中,用户首先自定义方法WorkThread,用于输出一组数据;然后在Main方法中,创建ThreadStart委托的实例work;接着通过work构造Thread类的实例th,这样就创建好一个线程;最后通过Start方法,启动工作线程。中止线程使用Abort方法。线程被中止,就停止运行,是无法恢复的,因为Windows会永久地删除被中止线程的所有数据。跟挂起工作线程时的结果一样,中止工作线程后,工作线程自然不会被执行。

工作线程WorkThread-->i=100000000
工作线程WorkThread-->i=200000000

线程被终止
  1. Join方法
    Join方法用于等待线程中止,如果后续的处理依赖于另一个已经终止的线程,可以调用Join方法,等待线程中止。该方法有三种重载形式:
public void Join() 
public void Join(int millisecondsTimeout)
public void Join(TimeSpan timeout)

参数说明:millisecondsTimeout表示等待线程终止的毫秒数。如果线程已终止,则返回值为true,如果线程经过了millisecondsTimeout指定时间后未终止,返回值为false。timeout表示等待线程终止的时间量TimeSpan。如果线程已终止,则返回值为true,如果线程经过timeout时间量之后未终止,则返回值为false。
编写程序,使用Join方法等待线程终止。

using System;
using System.Threading;
namespace Project
{
    class Program
    {
        static void Main(string[] args)
        {
            ThreadStart work = new ThreadStart(WorkThread);   //创建工作线程
            Thread th = new Thread(work);
            th.Start();    //启动线程
            //th.Join();
            th.Join(1000);//等待工作线程中止(修改代码)
            MainThread();
        }
        static void WorkThread()
        {
            for (long i = 1; i < 1000000000; i++)
            {
                if (i % 100000000 == 0 && i != 0)
                {
                    Console.WriteLine("工作线程WorkThread-->i={0}", i);
                }
            }
            Console.WriteLine("工作线程执行完毕");
        }
        static void MainThread()
        {
            long gap = 0;
            for (long i = 1000000000; i >= 0; i--)
            {
                gap = i - 1;
                if (i % 100000000 == 0)
                {
                    Console.WriteLine("主线程  MainThread-->i={0}", i);
                }
            }
            Console.WriteLine("主线程执行完毕");
            Console.ReadKey();
        }
    }
}

【程序分析】本例演示了线程的等待终止。在Main方法中,工作线程调用了Join方法,因此,需待工作线程中止后,主线程才会被执行。Join的其他重载方法可以指定等待的时间期限,超过了这个时间期限,程序也会继续执行。因此,可以将“th.Join();”语句修改为“th.Join(1000);”。

工作线程WorkThread-->i=100000000
工作线程WorkThread-->i=200000000
工作线程WorkThread-->i=300000000
工作线程WorkThread-->i=400000000
工作线程WorkThread-->i=500000000
工作线程WorkThread-->i=600000000
工作线程WorkThread-->i=700000000
工作线程WorkThread-->i=800000000
工作线程WorkThread-->i=900000000
工作线程执行完毕
主线程  MainThread-->i=1000000000
主线程  MainThread-->i=900000000
主线程  MainThread-->i=800000000
主线程  MainThread-->i=700000000
主线程  MainThread-->i=600000000
主线程  MainThread-->i=500000000
主线程  MainThread-->i=400000000
主线程  MainThread-->i=300000000
主线程  MainThread-->i=200000000
主线程  MainThread-->i=100000000
主线程  MainThread-->i=0
主线程执行完毕
主线程  MainThread-->i=1000000000
工作线程WorkThread-->i=100000000
工作线程WorkThread-->i=200000000
主线程  MainThread-->i=900000000
工作线程WorkThread-->i=300000000
主线程  MainThread-->i=800000000
工作线程WorkThread-->i=400000000
主线程  MainThread-->i=700000000
工作线程WorkThread-->i=500000000
主线程  MainThread-->i=600000000
工作线程WorkThread-->i=600000000
主线程  MainThread-->i=500000000
工作线程WorkThread-->i=700000000
主线程  MainThread-->i=400000000
工作线程WorkThread-->i=800000000
主线程  MainThread-->i=300000000
工作线程WorkThread-->i=900000000
工作线程执行完毕
主线程  MainThread-->i=200000000
主线程  MainThread-->i=100000000
主线程  MainThread-->i=0
主线程执行完毕

线程的优先级

线程的优先级可以通过Thread类的Priority属性设置,Priority属性是一个ThreadPriority型枚举,列举了5个优先等级:AboveNormal、BelowNormal、Highest、Lowest、Normal。普通线程的优先级默认为Normal;如果想有更高的优先级,可设置为AboveNormal或Highest;如果想有较低的优先级,可设置为BelowNormal或Lowest。线程优先级值,从高到低按顺序如下表所示。
在这里插入图片描述
可以通过调用线程的Priority属性来获取和设置其优先级。Priority属性用来获取或设置一个值,该值指示线程的调度优先级。
编写程序,分别创建两个线程,然后通过设定不同的优先级来显示线程的名称和优先级。

using System;
using System.Threading;
namespace Project7
{
    class Program
    {
        public static void method()
        {
            //输出线程的名称
            Console.WriteLine("线程名称:{0}",Thread.CurrentThread.Name.ToString());
            //输出线程的优先级
            Console.WriteLine("线程的优先级:{0}",Thread.CurrentThread.Priority.ToString());
        }
        static void Main(string[] args)
        {
            ThreadStart ts1 = new ThreadStart(method);
            ThreadStart ts2 = new ThreadStart(method);
            Thread t1 = new Thread(ts1);
            Thread t2 = new Thread(ts2);
            //为两个线程命名
            t1.Name = "学习C#线程一";
            t2.Name = "学习Java线程二";
            //指定线程t1的优先级为Highest
            t1.Priority = ThreadPriority.Highest;
            //启动两个线程
            t1.Start();
            t2.Start();
            Console.ReadKey();
        }    
    }
}

【程序分析】本例演示了线程的优先级。在代码中用户自定义方法method,用于输出线程的名称和优先级;然后在Main方法中,创建两个线程t1和t2,首先使用Name属性为两个线程命名,再使用Priority属性设置线程t1的优先级为Highest,最后启动两个线程。通过最后的输出结果发现,t1的优先级值为Highest,t2的优先级值为Normal,这是因为Normal是线程的默认值。

线程名称:学习C#线程一
线程的优先级:Highest
线程名称:学习Java线程二
线程的优先级:Normal
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值