C#中的进程检测退出事件和座位状态改变事件深入浅出谈谈EventHandler的使用

2022/09/03 实例 共 2359 字,约 7 分钟

关于进程

之前我在启动我的师生对讲的exe的时候,都是直接调用Process类的静态函数Process.Start(System.String AppPath,System.String Arguments) 来直接启动一个exe,这样当然是可以的,但是当我们的进程退出或者意外崩溃的时候,却没有办法对这个进程进行相关的检测,也就是说如果进程中途退出了的话,可能会导致整个框架的互斥等状态未发生改变,这个时候就需要用到一个进程对象

也就是说我们可以先实例化一个进程的对象Process p_VideoMeet,然后再用这个进程p_VideoMeet来表示我们整个运行着的进程,也就不用再做一些没什么含义的启动检测啊,状态码之类的东西了。所以对于此,我在这里写一个相关的实例。

比如我现在一个类,LBD_VideoMeet类,我可能在这个类内启动两个进程之中的一个,之前我们在使用的时候,是直接通过Process.Start这个静态函数启动,然后记录其启动的状态,其实这样的调用容易导致一些混乱的状态,而且有可能程序的意外退出,如果崩溃的话就没法知道当前的进程状态了,没有通知的情况,会导致无法获得互斥状态,如果这样的话,就没法清除当前状态了。

那么现在来上实例。

假设我们现在可以获得两个程序,Intercom.exe和 Broadcast.exe的启动路径和启动参数,而且当我们启动的时候就会向我们的框架中发送句柄,那我们现在应该怎么做呢?

首先我们当然是希望打开的子进程不脱离我们的主进程,也就是我们在主进程中可以有完整的子进程,所以不能像野狗拉屎一样,把子进程拉出来放在大街上随风而去就完了(当然考虑到高内聚低耦合的原则,这肯定是最好的状态,打开的子进程有完整独立的功能,而需要整合其中的程序用dll来表示,但是开发中难免有些妥协,比如开源,或者跨语言的程序,或者像我这样的新手写dll没法保证内存和线程的安全性)

那我们就用一个进程来表示我们现在需要启动的进程 Process p_VideoMeet,因为Intercom和Broadcast是互斥的,所以两个共享一个进程类就行了,反正这个进程退出的时候也会释放掉所有的资源,所以不需要操心。甚至这样操作可以省去很多不必要的判别,直接释放进程类资源即可。

原先没有参悟到这个精髓写出来的大便现在再回过头来看真是令人羞愧,但是能跑告诉公路的大便,谁在乎他会不会有轮子呢?

我们先设置一个进程对象

 Process p_VideoMeet = null;

启动进程的方法:

 public void StartProcess(System.String strAppPath, System.String Argus)
      {
          try
          {
              if(this.p_VideoMeet == null)
              {
                  p_VideoMeet = new Process();
              }

              p_VideoMeet.StartInfo.FileName = strAppPath; //启动进程具体路径
              p_VideoMeet.StartInfo.Arguments = Argus; //启动项参数
              p_VideoMeet.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
              p_VideoMeet.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
              p_VideoMeet.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息
              p_VideoMeet.StartInfo.RedirectStandardError = true;//重定向标准错误输出
              p_VideoMeet.StartInfo.CreateNoWindow = false;//不显示程序窗口
              p_VideoMeet.EnableRaisingEvents = true;

              //意外退出的话,我这边也可以得到消息了
              p_VideoMeet.Exited += this.P_Exited;

              p_VideoMeet.Start();

          }
          catch (Exception e)
          {
              WriteErrorMessage("CheckClientExitMessages:" + e.Message);

          }
      }

意外退出事件

public static event EventHandler ExitedEvent;

private static void P_Exited(object sender, EventArgs e)
{
    if (ExitedEvent!=null)
    {
        ExitedEvent(sender,e);
    }   
}

最伟大的设计,就是最简单的设计。

关于事件和委托

其实我个人在开发过程中是比较抵触事件和委托这个叫法的,就有点像socket通讯里管socket叫套接字 这种翻译一样,即使到了我还是觉得所谓的套接字没有 发包 这两个字来的简介明了。

如果要换一种说法,我们要怎么理解呢?其实就像是触发器和接收器 – 当我们按下触发器之后,所有的接收器都会接到触发器发送来的信号。打个比方,就好像烽火狼烟,我一点火,所有的哨站就知道开干了,这种情况下烽火只能传递一个简单信号:起火等于开干,但是这也是只有其他哨所才懂其中的含义;或者海上的灯塔,按照一定的频率和强度打信号,海上的渔船就能看得懂灯塔打来的信号,这样传递的信息就更加复杂了,这些传递的信息也只有这个海域的渔船们才会懂,不同的海域可能会有不同的约定俗成的信号模式。

image

C#的事件委托大致和我上面说的这两种模型差不多,都分为 1.触发器,即发送信号的方法 2.接收器,即接收到信号并触发行为的方法

之前我也有些过一篇博客,有关于事件和委托相关的内容的,详情见下方博客

轩先生-主框架代码中,关于委托的一些事,开发日志

文档信息

Search

    Table of Contents