C#线程简单使用

1. Thread

Thread默认开启前台线程。 其他的开启方式默认开启后台线程。

  1. 首先导入命名空间:
    System.Threading

  2. 实例化一个Thread对象

Thread newThread = new Thread(AMethod);
 // AMethod,为该线程将要执行的任务。
  1. 启动线程
    若要开始执行线程,可使用Start方法
newThread.Start();
  1. 停止线程
newThread.Abort();

Thread线程的多种常用方法列表

方法操作
Start使线程开始运行
Sleep使线程暂停指定的一段时间。
Suspend在线程到达安全点时,使其暂停。
Abort在线程到达安全点时,使其停止。
Resume重新启动挂起的线程
Join使当前线程一直等到另一线程完成。 在与超时值一起使用时,如果该线程在分配的时间内完成,此方法将返回 True。

**安全点: **
安全点是指代码中公共语言运行时可以安全地执行自动“垃圾回收”的位置。垃圾回收是指释放不再使用的变量并回收内存的过程。 调用线程的 Abort 或 Suspend 方法时,公共语言运行时将对代码进行分析,确定让线程停止运行的适当位置。

Thread的相关属性:

属性
IsAlive如果线程处于活动状态,则包含值 True。
IsBackground获取或设置一个布尔值,该值表示一个线程是否是,或是否应当是后台线程。 后台线程与前台线程类似,但后台线程不阻止进程停止。 一旦某个进程的所有前台线程都停止,公共语言运行时就会对仍处于活动状态的后台线程调用 Abort 方法,从而结束该进程。
Name获取或设置线程的名称。 通常用于在调试时发现各个线程。
Priority获取或设置操作系统用于确定线程调度优先顺序的值。
ApartmentState获取或设置用于特定线程的线程模型。 线程模型在线程调用非托管代码时很重要。
ThreadState包含描述线程状态的值。

线程优先级
每个线程都有一个优先级属性,用于确定其执行所占用的处理器时间片大小。 操作系统为高优先级线程分配较长的时间段,并为低优先级线程分配较短的时间段。 新创建的线程具有值 Normal,但可以将 Priority 属性更改为 ThreadPriority 枚举中的任何值

2. 通过委托来开启线程

通过委托,调用BeginInvoke 方法来开启一条线程,去执行该委托所指向的方法。


        // 线程执行该方法
        static string test1(int x, int y)
        {
            Console.WriteLine(x + y);
            return x + "+"+ y;
        }

        static void Main(string[] args)
        {

            Func<int, int, string> fun1 = test1;
            // 通过委托来开启线程执行。 倒数第二个参数是,线程执行完毕之后的回调方法, 倒数第一个参数是,执行完之后,携带的参数。
            fun1.BeginInvoke(10, 20, test1CallBack, fun1);
            
        }

        // 通过委托来传递回调函数,会自动将该线程的执行结果 传递过来
        static void test1CallBack(IAsyncResult ar)
        {
            //AsyncState 获取所携带的参数,在这里就是上面fun1.BeginInvoke(10, 20, test1CallBack, fun1); 这行代码中,所传递的fun1
            Func<int, int, string> fun1 = ar.AsyncState as Func<int, int, string>;
            // 获取委托所指向的方法的执行结果。
            string result =  fun1.EndInvoke(ar);
            Console.WriteLine("这就是结果" + result);
        }

3. 线程池

       static void ThreadFunc3()
        {
            Console.WriteLine("--------");
            // 调用线程池来执行任务。 每调用一次,就会开启一条线程来执行该任务。
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            ThreadPool.QueueUserWorkItem(test3);
            Console.WriteLine("========");
            Thread.Sleep(100);
        }

        // 线程池调用的方法,需要一个object类型的参数方法,且不能有返回值
        static void test3(object obj)
        {
            Thread.CurrentThread.IsBackground = false;
            Console.WriteLine("asdas");
        }

4. Task 开启

        static void ThreadMethod()
        {
            Console.WriteLine("ThreadMethod Begin" + Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(1000);
            Console.WriteLine("Thread End");
        }

        static void continueTask(Task t)
        {
            Console.WriteLine("task is continue" + t.Id);
            Thread.Sleep(3000);
            Console.WriteLine("task is complete");
        }

        static void Main(string[] args)
        {
            // 第一种方式开启
            //Task t = new  Task(ThreadMethod);
            //t.Start();

             第二种方式开启
            //TaskFactory tf = new TaskFactory();
            //tf.StartNew(ThreadMethod);

            Task t1 = new Task(ThreadMethod);  
            Task t2 = t1.ContinueWith(continueTask);

            t1.Start(); // 开启任务 t1, 当t1执行完毕的时候,会执行t2的任务

            Console.ReadKey();
        }

5. 线程使用问题

  1. 资源竞争
    多个线程访问同一个资源,对同一个资源做修改,会引发数据混乱。
  2. 死锁
    多把锁。互相牵制。导致线程都互相等待解锁。
  3. 案例:
  4. 银行存取款
  5. 多窗口同时卖票
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TestProject
{
    class SaleTicket
    {
        private Thread thread1;
        private Thread thread2;
        private Thread thread3;
        private int ticketCount = 1000;

        public SaleTicket()
        {
            thread1 = new Thread(Sale);
            thread2 = new Thread(Sale);
            thread3 = new Thread(Sale);
        }

        public void Sale()
        {
            while(true)
            {
                lock(this)
                {
                    if (ticketCount > 0)
                    {
                        ticketCount -= 1;
                        Console.WriteLine(Thread.CurrentThread.Name + "卖了一张票,剩余" + ticketCount);
                    }
                    else
                    {
                        Console.WriteLine(Thread.CurrentThread.Name + ":票卖完了");
                        break;
                    }
                }
            }
        }

        public void StartSaleTicket()
        {
            thread1.Start();
            thread2.Start();
            thread3.Start();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值