• 网络编程——第一篇 基础之进程线程


       在C#的网络编程中,进程和线程是必备的基础知识,同时也是一个重点,所以我们要好好的掌握一下。

    一:概念

              首先我们要知道什么是”进程”,什么是“线程”,好,查一下baike。

      进程:是一个具有一定独立功能的程序关于某个数据集合的一次活动。它是操作系统动态执行的基本单元,

               在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

      线程:是"进程"中某个单一顺序的控制流。

      

    关于这两个概念,大家稍微有个印象就行了,防止以后被面试官问到。

    二:进程

           framework里面对“进程”的基本操作的封装还是蛮好的,能够满足我们实际开发中的基本应用。

    <1> 获取进程信息

           framework中给我们获取进程的方式还是蛮多的,即可以按照Name获取,也可以按照ID获取,也可以获取本地和远程的进程信息。

    1    public Process[] GetProcess(string ip = "")
    2 {
    3 if (string.IsNullOrEmpty(ip))
    4 return Process.GetProcesses();
    5
    6 return Process.GetProcesses(ip);
    7 }
     Process process = Process.GetProcessById(Convert.ToInt32(processID));

    <2> 启动和停止进程

      其实这个也没啥好说的,不过有一个注意点就是Process中的"kill"和"CloseMainWindow"的区别。

      windowMainWindow:  当我们打开的Process是一个有界面的应用程序时,推荐使用此方法,它相当于点击了应用程序的关闭按钮,是一个有序的

                                      终止应用程序的操作,而不像kill那么暴力。   

      kill:                         根据这个单词估计大家都知道啥意思吧,它的作用就是强制关闭我们打开的Process,往往会造成就是我们数据的丢失,所以

                                     说在万不得已的情况下不要使用kill,当然在无图形界面的应用程序中,kill是唯一能够结束Process的一个策略。

    <3> 进程操作的一个演示

      1    public class ProgessHelper
    2 {
    3 //主操作流程
    4 public static void MainProcess()
    5 {
    6 ProgessHelper helper = new ProgessHelper();
    7
    8 var result = helper.GetProcess();
    9
    10 helper.ShowProcess(result.Take(10).ToArray());
    11
    12 Console.Write("\n请输入您要查看的进程:");
    13
    14 helper.ShowProcessSingle(Console.ReadLine());
    15
    16 Console.Write("\n请输入您要开启的程序:\t");
    17
    18 var name = helper.StartProcess(Console.ReadLine());
    19
    20
    21 Console.WriteLine("程序已经开启,是否关闭?(0,1)");
    22
    23 if (Console.ReadLine() == "1")
    24 {
    25 helper.StopProcess(name);
    26
    27 Console.WriteLine("关闭成功。");
    28 }
    29 }
    30
    31 #region 获取进程
    32 /// <summary>
    33 /// 获取进程
    34 /// </summary>
    35 /// <param name="ip"></param>
    36 /// <returns></returns>
    37 public Process[] GetProcess(string ip = "")
    38 {
    39 if (string.IsNullOrEmpty(ip))
    40 return Process.GetProcesses();
    41
    42 return Process.GetProcesses(ip);
    43 }
    44 #endregion
    45
    46 #region 查看进程
    47 /// <summary>
    48 /// 查看进程
    49 /// </summary>
    50 /// <param name="process"></param>
    51 public void ShowProcess(Process[] process)
    52 {
    53 Console.WriteLine("进程ID\t进程名称\t物理内存\t\t启动时间\t文件名");
    54
    55 foreach (var p in process)
    56 {
    57 try
    58 {
    59 Console.WriteLine("{0}\t{1}\t{2}M\t\t{3}\t{4}", p.Id, p.ProcessName.Trim(), p.WorkingSet64 / 1024.0f / 1024.0f,
    60 p.StartTime, p.MainModule.FileName);
    61 }
    62 catch (Exception ex)
    63 {
    64 Console.WriteLine(ex.Message);
    65 }
    66 }
    67 }
    68 #endregion
    69
    70 #region 根据ID查看指定的进程
    71 /// <summary>
    72 /// 根据ID查看指定的进程
    73 /// </summary>
    74 /// <param name="processID"></param>
    75 public void ShowProcessSingle(string processID)
    76 {
    77 Process process = Process.GetProcessById(Convert.ToInt32(processID));
    78
    79 Console.WriteLine("\n\n您要查看的进程详细信息如下:\n");
    80
    81 try
    82 {
    83 var module = process.MainModule;
    84
    85 Console.WriteLine("文件名:{0}\n版本{1}\n描叙{2}\n语言:{3}", module.FileName, module.FileVersionInfo.FileVersion,
    86 module.FileVersionInfo.FileDescription,
    87 module.FileVersionInfo.Language);
    88 }
    89 catch (Exception e)
    90 {
    91 Console.WriteLine(e.Message);
    92 }
    93 }
    94 #endregion
    95
    96 #region 进程开启
    97 /// <summary>
    98 /// 进程开启
    99 /// </summary>
    100 /// <param name="fileName"></param>
    101 /// <returns></returns>
    102 public string StartProcess(string fileName)
    103 {
    104 Process process = new Process();
    105
    106 process.StartInfo = new ProcessStartInfo(fileName);
    107
    108 process.Start();
    109
    110 return process.ProcessName;
    111 }
    112 #endregion
    113
    114 #region 终止进程
    115 /// <summary>
    116 /// 终止进程
    117 /// </summary>
    118 /// <param name="name"></param>
    119 public void StopProcess(string name)
    120 {
    121 var process = Process.GetProcessesByName(name).FirstOrDefault();
    122
    123 try
    124 {
    125 process.CloseMainWindow();
    126 }
    127 catch (Exception ex)
    128 {
    129 Console.WriteLine(ex.Message);
    130 }
    131 }
    132 #endregion
    133 }

    快看,PPTV真的被我打开了,嗯,8错,Process还是蛮好玩的。

    这里要注意一点:

          我们在59行中加上了Try Catch,这是因为每个Process都有一个MainModule属性,但并不是每一个MainModule都能被C#获取,

          如会出现如下的“拒绝访问”。


     

    三: 线程

          同样线程的相关操作也已经被framework里面的Thread完美的封装,大大简化了我们的工作量,常用的操作如下

       <1> 启动线程。

       <2> 终止线程。

       <3> 暂停线程。

       <4> 合并线程。

                 这个要解释一下,比如:t1线程在执行过程中需要等待t2执行完才能继续执行,此时我们就要将t2合并到t1中去,也就是在

              t1的代码块中写上t2.Join()即可。同样Join中也可以加上等待t2执行的时间,不管t2是否执行完毕。

       <5> 线程同步

                估计大家也知道,多线程解决了系统的吞吐量和响应时间,同时也给我们留下了比如死锁,资源争用等问题,那么我们如何

              解决这些问题呢?呵呵,Anders Hejlsberg 这位老前辈已经给我们提供了很多的实现同步线程的类,比如Mutex,Monitor,

              Interlocked和AutoResetEvent,当然在实际应用中,我们还是喜欢使用简化版的lock,因为这玩意能够使编程简化,同时使

             程序看起来简洁明了。 

     <6>  同样我也举个例子

     1 public class ThreadHelper
    2 {
    3 public static void MainThread()
    4 {
    5
    6 ThreadHelper helper = new ThreadHelper(100);
    7
    8 Thread[] thread = new Thread[20];
    9
    10 for (int i = 0; i < 20; i++)
    11 {
    12 thread[i] = new Thread(helper.DoTransactions);
    13
    14 thread[i].Name = "线程" + i;
    15
    16 }
    17
    18 foreach (var single in thread)
    19 {
    20 single.Start();
    21 }
    22 }
    23
    24 int balance;
    25
    26 object obj = new object();
    27
    28 public ThreadHelper(int balance)
    29 {
    30 this.balance = balance;
    31 }
    32
    33 #region 取款操作
    34 /// <summary>
    35 /// 取款操作
    36 /// </summary>
    37 /// <param name="amount"></param>
    38 public void WithDraw(int amount)
    39 {
    40 lock (obj)
    41 {
    42 if (balance <= 0)
    43 {
    44 Console.WriteLine("哈哈,已经取完了");
    45 return;
    46 }
    47
    48 if (balance >= amount)
    49 {
    50 Console.WriteLine("取款前余额:{0},取款:{1},还剩余额:{2}", balance, amount, balance - amount);
    51 balance = balance - amount;
    52 }
    53 else
    54 {
    55 Console.WriteLine("取款前余额:{0},取款:{1},还剩余额:{2}", balance, balance, balance = 0);
    56 }
    57 }
    58 }
    59 #endregion
    60
    61 #region 自动取款操作
    62 /// <summary>
    63 /// 自动取款操作
    64 /// </summary>
    65 public void DoTransactions(object obj)
    66 {
    67 int random = new Random().Next(4, 10);
    68
    69 Thread.Sleep(5000);
    70
    71 WithDraw(random);
    72 }
    73 #endregion
    74 }

    当我们加上lock的时候一切正常,但是当我们把lock去掉的时候,看看线程们会有“争用资源”的现象吗?,在下图中可以看到,出现了如下的现象,

    当然这不是我想看到的结果,如果在实际应用中会是多么难找的bug。

    <8> 线程池

         上面的例子中,我创建了20个线程来完成任务,比如在某些实际应用中,Client端的每个请求Server都需要创建一个线程来处理,

         那么当线程很多的时候并不是一件好事情,这会导致过度的使用系统资源而耗尽内存,那么自然就会引入“线程池”。

         线程池:是一个在后台执行多个任务的集合,他封装了我们对线程的基本操作,我们能做的就只要把“入口方法”丢给线程池就行了。

         特点:  线程池有最大线程数限制,大小在不同的机器上是否区别的,当池中的线程都是繁忙状态,后入的方法就会排队,直至池中有空闲

                   的线程来处理。

         代码: 修改后如下

     1         public static void MainThread()
    2 {
    3
    4 ThreadHelper helper = new ThreadHelper(100);
    5
    6 for (int i = 0; i < 20; i++)
    7 {
    8 ThreadPool.QueueUserWorkItem(new WaitCallback(helper.DoTransactions));
    9 }
    10
    11 //Thread[] thread = new Thread[20];
    12
    13 //for (int i = 0; i < 20; i++)
    14 //{
    15 // thread[i] = new Thread(helper.DoTransactions);
    16
    17 // thread[i].Name = "线程" + i;
    18
    19 //}
    20
    21 //foreach (var single in thread)
    22 //{
    23 // single.Start();
    24 //}
    25 }

  • 相关阅读:
    模板 无源汇上下界可行流 loj115
    ICPC2018JiaozuoE Resistors in Parallel 高精度 数论
    hdu 2255 奔小康赚大钱 最佳匹配 KM算法
    ICPC2018Beijing 现场赛D Frog and Portal 构造
    codeforce 1175E Minimal Segment Cover ST表 倍增思想
    ICPC2018Jiaozuo 现场赛H Can You Solve the Harder Problem? 后缀数组 树上差分 ST表 口胡题解
    luogu P1966 火柴排队 树状数组 逆序对 离散化
    luogu P1970 花匠 贪心
    luogu P1967 货车运输 最大生成树 倍增LCA
    luogu P1315 观光公交 贪心
  • 原文地址:https://www.cnblogs.com/ShaYeBlog/p/2680478.html
Copyright © 2020-2023  润新知