C#进程与线程学习笔记

1、多线程
进程类是指 Process 类,该类所在的命名空间是 System.Diagnostics。线程状态控制的方法包括暂停线程 (Sleep)、中断线程 (Interrupt)、挂起线程 (Suspend)、唤醒线程 (Resume)、终止线程 (Abort)。

Process[] processes = Process.GetProcesses();
        foreach(Process p in processes)
        {
            richTextBox1.Text = richTextBox1.Text + p.ProcessName + "\r\n";
        }
  //设置进程名称
        Process p = new Process();
        p.StartInfo.FileName = ProcessName;
        //启动进程
        p.Start();

2、在使用 Thread 类的构造方法创建其实例时,需要用到 ThreadStart 委托或者 ParameterizedThreadStart 委托创建 Thread 类的实例。
Thread.Sleep(1000);

ThreadStart 委托只能用于无返回值、无参数的方法,ParameterizedThreadStart 委托则可以用于带参数的方法。
ThreadStart ts = new ThreadStart( 方法名 );
Thread t = new Thread(ts);
t.Priority = ThreadPriority.Lowest;
t.Start();


ParameterizedThreadStart pts=new ParameterizedThreadStart( 方法名 );
Thread t=new Thread(pts);

        ParameterizedThreadStart pts = new ParameterizedThreadStart(PrintEven);
        Thread t = new Thread(pts);
        t.Start(10)            void PrintEven(Object n)

ParameterizedThreadStart pts = new ParameterizedThreadStart(PrintEven);
 ParameterTest pt = new ParameterTest(1, 10);
        Thread t = new Thread(pts);
        t.Start(pt);


3、实现线程同步可以使用 lock 关键字和 Monitor 类、Mutex 类来解决。
 lock 关键字能保证加锁的线程只有在执行完成后才能执行其他线程。
lock(object)
{
    //临界区代码
}

Monitor 类的命名空间是 System.Threading
使用 Monitor 类锁定资源的代码如下。
Monitor.Enter(object);
try
{
    //临界区代码
}
finally
{
    Monitor.Exit(object);
}
Mutex 类也是用于线程同步操作的类,例如,当多个线程同时访问一个资源时保证一次只能有一个线程访问资源。
WaitOne() 方法用于等待资源被释放, ReleaseMutex() 方法用于释放资源。

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
using System.Threading;       //Thread类
using System.Diagnostics;     // Process类
namespace Threat
{
    class Program
    {

        /// <summary>
        /// 模拟发红包,当剩余五个时线程终止
        /// </summary>
        private static int count = 10;
        private static void GiveRedEnvelop()
        {
            while (count > 0)
            {
                count--;
                if (count == 4)
                {
                    //终止当前线程
                    Console.WriteLine("红包暂停发放!");
                    //                  Thread.CurrentThread.Abort(); //调用此方法通常会终止线程。
                }
                Console.WriteLine("剩余 {0} 个红包", count);
            }
        }


        private static Mutex mutex = new Mutex();    // 互斥
        public static void PakingSpace(object num)
        {
            if (mutex.WaitOne())
            {
                try
                {
                    Console.WriteLine("车牌号{0}的车驶入!", num);
                    Thread.Sleep(1000);
                }
                finally
                {
                    Console.WriteLine("车牌号{0}的车离开!", num);
                    mutex.ReleaseMutex();
                }
            }
        }
        static void Main(string[] args)
        {
            #region 进程相关
            /*
            Process[] processes = Process.GetProcesses();   //获取所有进程
            foreach (Process p in processes)
            {
                Console.WriteLine(p.ProcessName + "\r\n");
            }

            //创建Process 类的对象                           //启动某个进程
            Process p1 = new Process();
            Console.Write("输入要启用的进程的名字:");
            string proceeName = Console.ReadLine();
            //设置进程名称
            p1.StartInfo.FileName = Convert.ToString(proceeName);
            //启动进程
            p1.Start();


            //关闭进程
            Console.Write("输入要关闭的进程的名字:");
            string proceeNameStop = Console.ReadLine();
            Process[] processesstop = Process.GetProcessesByName(proceeNameStop);
            //判断是否存在指定进程名称的进程
            if (processesstop.Length > 0)
            {
                try
                {
                    foreach (Process p in processesstop)
                    {
                        //判断进程是否处于运行状态
                        if (!p.HasExited)
                        {
                            //关闭进程
                            p.Kill();
                            Console.WriteLine(p.ProcessName + "已关闭!");
                            //获取所有进程信息
                            processes = Process.GetProcesses();
                        }
                    }
                }
                catch
                {
                    Console.WriteLine("该进程无法关闭!");
                }
            }*/
            #endregion


            #region 线程初识
            /*
            // 第一个线程,打印偶数
            //ThreadStart 委托只能用于无返回值、无参数的方法,ParameterizedThreadStart 委托则可以用于带参数的方法。具体实例看mutex部分
            ThreadStart ts1 = new ThreadStart(PrintEven);  // 使用ThreadStart委托为PrintEvent方法创建ThreadStart委托的实例 
            Thread t1 = new Thread(ts1);                   //创建Thread类的实例

            优先级的值通过 ThreadPriority 枚举类型来设置,从低到高分别为Lowest、BelowNormal、Normal、AboveNormal、Highest。默认的优先级是 Normal。
            每次输出的结果也不是固定的。通过优先级是不能控制线程中的先后执行顺序的,只能是优先级高的线程优先执行的次数多而已。
            t1.Priority = ThreadPriority.Highest;

             线程状态控制的方法包括暂停线程(Sleep)、中断线程(Interrupt)、挂起线程(Suspend)、唤醒线程(Resume)、终止线程(Abort)。
            //使用暂停线程(Sleep) 的方法让打印奇数和打印偶数的线程交替执行,

            //第二个线程,打印奇数
            ThreadStart ts2 = new ThreadStart(PrintOld);
            Thread t2 = new Thread(ts2);
            t2.Priority = ThreadPriority.Highest;


            t1.Start();    // 通过Start方法启动线程并调用PrintEven()方法
            t2.Start();    // 通过Start方法启动线程并调用PrintOld()方法      两个线程由于没有对线程的执行顺序和操作做控制,所以运行该程序每次打印的值的顺序是不一样的。


            //使用 ParameterizedThreadStart 创建进程,首先需要创建 ParameterizedThreadStart委托调用带参数的方法时,方法中的参数只能是 object 类型并且只能含有一个参数。
            //传递一个参数的线程
            ParameterizedThreadStart pts = new ParameterizedThreadStart(PrintEven1);
            Thread t = new Thread(pts);
            t.Start(20);
            t.Priority = ThreadPriority.Highest;

            //引用多个参数的方法
            ParameterizedThreadStart pts3 = new ParameterizedThreadStart(PrintEven2);
            ParameterTest pt3 = new ParameterTest(1, 30);
            Thread t3 = new Thread(pts3);
            t3.Start(pt3);
            */
            #endregion


            #region 发红包线程模拟
            ThreadStart hb = new ThreadStart(GiveRedEnvelop);
            Thread h = new Thread(hb);
            h.Start();

            使用 Thread 对象的 IsBackground 属性来判断线程是否为后台线程。,在应用程序运行结束后,后台线程即使没有运行完也会结束,前台线程必须等待自身线程运行结束后才会结束。
            if (h.IsBackground == false)
            {
                Console.WriteLine("该线程不是后台线程!");
                h.IsBackground = true;

            }
            else
            {
                Console.WriteLine("该线程是后台线程!");
            }
            #endregion


            #region Lock、Monitor、Mutex
            实现线程同步可以使用 lock 关键字和 Monitor 类、Mutex 类来解决

            // 1、lock:给线程加锁,保证线程同步.线程同步的方法是将线程资源共享,允许控制每次执行一个线程,并交替执行每个线程。
            /*通过 lock 关键字能保证加锁的线程只有在执行完成后才能执行其他线程。
            先执行奇数线程,再执行偶数线程。*/
            Program program = new Program();
            ThreadStart ts4 = new ThreadStart(program.LockPrintOdd);
            Thread t4 = new Thread(ts4);
            t4.Name = "打印奇数的线程";
            t4.Start();
            ThreadStart ts5 = new ThreadStart(program.LockPrintEven);
            Thread t5 = new Thread(ts5);
            t5.Name = "打印偶数的线程";
            t5.Start();


            //2、Monitor
            /*Monitor 类的用法虽然比 lock 关键字复杂,但其能添加等待获得锁定的超时值,这样就不会无限期等待获得对象锁。
            使用 TryEnter() 方法可以给它传送一个超时值,决定等待获得对象锁的最长时间。
            使用 TryEnter() 方法设置获得对象锁的时间的代码如下。
            Monitor.TryEnter(object, 毫秒数);该方法能在指定的毫秒数内结束线程,这样能避免线程之间的死锁现象
            Monitor 类中的 Wait() 方法让线程等待一定的时间,使用 Pulse() 方法通知处于等待状态的线程*/
            ThreadStart ts6 = new ThreadStart(program.MonitorPrintOdd);
            Thread t6 = new Thread(ts4);
            t6.Name = "打印奇数的线程";
            t6.Start();
            ThreadStart ts7 = new ThreadStart(program.MonitorPrintEven);
            Thread t7 = new Thread(ts7);
            t7.Name = "打印偶数的线程";
            t7.Start();


            //3、Mutex 类也是用于线程同步操作的类
            /*当多个线程同时访问一个资源时保证一次只能有一个线程访问资源。
            在 Mutex 类中,WaitOne() 方法用于等待资源被释放, ReleaseMutex() 方法用于释放资源。
            WaitOne() 方法在等待 ReleaseMutex() 方法执行后才会结束。*/
            ParameterizedThreadStart tc = new ParameterizedThreadStart(PakingSpace);
            Thread t8 = new Thread(tc);
            t8.Start("冀A12345");
            Thread t9 = new Thread(tc);
            t9.Start("京A00000");

            #endregion
        }


        /// <summary>
        /// 打印0~10中的偶数的方法
        /// </summary>
        private static void PrintEven()
        {
            for (int i = 0; i <= 10; i = i + 2)
            {
                //让线程休眠1S
                //Thread.Sleep(1000);
                Console.WriteLine(i);
            }
        }

        /// <summary>
        /// 打印1~10中的奇数的方法
        /// </summary>
        private static void PrintOld()
        {
            for (int i = 1; i <= 10; i = i + 2)
            {
                Console.WriteLine(i);

            }
        }

        /// <summary>
        /// 传递一个参数的打印偶数的方法
        /// </summary>
        /// <param name="n"></param>
        private static void PrintEven1(object n)
        {
            for (int i = 0; i <= (int)n; i = i + 2)
            {
                Console.WriteLine(i);
            }
        }

        /// <summary>
        /// 传递多个参数的打印偶数的方法
        /// </summary>
        /// <param name="n"></param>
        private static void PrintEven2(object n)
        {
            //判断n是否为ParameterTest 类的对象
            if (n is ParameterTest)
            {
                int beginNum = ((ParameterTest)n).beginNum;   //获取对象中的第一个参数
                int endNum = ((ParameterTest)n).endNum;       //获取对象中的第二个参数

                for (int i = beginNum; i <= endNum; i++)
                {

                    if (i % 2 == 0)
                    {
                        Console.WriteLine(i);
                    }
                }
            }
        }


        /// <summary>
        /// Lock先执行奇数在执行偶数
        /// </summary>
        public void LockPrintEven()
        {
            lock (this)
            {
                for (int i = 0; i <= 10; i = i + 2)
                {
                    Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
                }
            }

        }
        public void LockPrintOdd()
        {
            lock (this)
            {
                for (int i = 1; i <= 10; i = i + 2)
                {
                    Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
                }
            }
        }

        /// <summary>
        /// Monitor
        /// </summary>
        public void MonitorPrintEven()
        {
            // Monitor 类的用法虽然比 lock 关键字复杂,但其能添加等待获得锁定的超时值,这样就不会无限期等待获得对象锁。
            //Monitor.TryEnter(object, 毫秒数);

            Monitor.TryEnter(this, 1);   //使用 TryEnter() 方法可以给它传送一个超时值,决定等待获得对象锁的最长时间。该方法能在指定的毫秒数内结束线程,这样能避免线程之间的死锁现象。
            Monitor.Enter(this);
            try
            {
                for (int i = 0; i <= 10; i = i + 2)
                {
                    Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
                }
            }
            finally
            {
                Monitor.Exit(this);
            }
        }
        public void MonitorPrintOdd()
        {
            Monitor.Enter(this);
            try
            {
                for (int i = 1; i <= 10; i = i + 2)
                {
                    Console.WriteLine(Thread.CurrentThread.Name + "--" + i);
                }
            }
            finally
            {
                Monitor.Exit(this);
            }
        }

    }
}

/// <summary>
/// 线程传递多个参数的构造方法
/// </summary>
public class ParameterTest
{
    public int beginNum;
    public int endNum;
    public ParameterTest(int a, int b)
    {
        this.beginNum = a;
        this.endNum = b;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值