zoukankan      html  css  js  c++  java
  • 一个更好一点的主线程与子线程之间通信的做法

      1 using System;
      2 using System.Threading;
      3 using System.Collections.Generic;
      4 
      5 namespace RemoteConsole
      6 {
      7     public delegate void RemoteConsoleMessageDelegate(object sender, RemoteConsoleMessageEventArgs e);
      8 
      9     public class TRemoteConsole
     10     {//我们定义了一系列的事件
     11         public event RemoteConsoleMessageDelegate ServerKeyCharEvent;
     12         public event RemoteConsoleMessageDelegate ServerShutdownEvent;
     13         public event RemoteConsoleMessageDelegate CloseClientEvent;
     14         public event RemoteConsoleMessageDelegate PauseClientEvent;
     15         public event RemoteConsoleMessageDelegate ListClientEvent;
     16 
     17         public List<TClientWaiter> clientGroup = new List<TClientWaiter>();
     18 
     19         public TClientWaiter AcceptNewClient()
     20         {
     21             //我们接受了一个client,并且把自身传递给过去,便于client引用
     22             TClientWaiter client = new TClientWaiter(this);
     23 
     24             //订阅了clientJoinEvent事件,注意这个事件是在TClientWaiter中定义的
     25             client.clientJoinEvent += ClientJoin;
     26 
     27             //我们用一个List包含了所有的client引用
     28             this.clientGroup.Add(client);
     29 
     30             Thread t = new Thread(new ThreadStart(client.connectionCreated));
     31             t.Name = String.Format("子线程{0}", clientGroup.Count);
     32             t.Start();
     33 
     34             return client;
     35         }
     36 
     37         //在上面,我们订阅了 clientJoinEvent 事件
     38         //所以一旦发生了 clientJoinEvent 事件,我们就能知道并且可以采取相应的行动
     39         public void ClientJoin(object sender, RemoteConsoleMessageEventArgs e)
     40         {
     41             Console.WriteLine("{0}进入", ((TClientWaiter)sender).currentThread.Name);
     42         }
     43 
     44         //以下几个都是触发事件的方法
     45         public void ServerKeyChar()
     46         {
     47             //注意,如果事件没有在任何一个地方被订阅的话,那么它等于null
     48             //触发一个等于null的事件会抛出异常,所以我们要先判断一下。
     49             if (this.ServerKeyCharEvent != null) {
     50                 this.ServerKeyCharEvent(thisnew RemoteConsoleMessageEventArgs("Server key char event"));
     51             } else {
     52                 Console.WriteLine("警告:没有定义任何处理 ServerKeyCharEvent 事件的方法");
     53             }
     54         }
     55 
     56         public void Shutdown()
     57         {
     58             if (this.ServerShutdownEvent != null) {
     59                 this.ServerShutdownEvent(thisnew RemoteConsoleMessageEventArgs("Server will shutdown after 10 minutes."));
     60             } else {
     61                 Console.WriteLine("警告:没有定义任何处理 ServerShutdownEvent 事件的方法");
     62             }
     63         }
     64 
     65         //这个是关闭所有client(子线程)的方法
     66         //我们可以通过迭代clientGroup这个List对象来取得所有client的引用来做
     67         //也可以利用事件机制向所有client线程发送消息来做到
     68         public void CloseCient()
     69         {
     70             if (this.CloseClientEvent != null) {
     71                 this.CloseClientEvent(thisnew RemoteConsoleMessageEventArgs("Close client connection."));
     72             } else {
     73                 Console.WriteLine("警告:没有定义任何处理 CloseClientEvent 事件的方法");
     74             }
     75         }
     76 
     77         public void PauseClient()
     78         {
     79             if (this.PauseClientEvent != null) {
     80                 this.PauseClientEvent(thisnew RemoteConsoleMessageEventArgs("Pause client thread."));
     81             } else {
     82                 Console.WriteLine("警告:没有定义任何处理 PauseClientEvent 事件的方法");
     83             }
     84         }
     85 
     86         public void ListClient()
     87         {
     88             if (this.ListClientEvent != null) {
     89                 this.ListClientEvent(thisnew RemoteConsoleMessageEventArgs("List client status."));
     90             } else {
     91                 Console.WriteLine("警告:没有定义任何处理 ListClientEvent 事件的方法");
     92             }
     93         }
     94 
     95         private static void Main()
     96         {
     97             TRemoteConsole RServer = new TRemoteConsole();
     98 
     99             //新进来了两个client
    100             TClientWaiter c1 = RServer.AcceptNewClient();
    101             TClientWaiter c2 = RServer.AcceptNewClient();
    102 
    103             while(true)
    104             {
    105                 ConsoleKeyInfo k = Console.ReadKey(true);
    106 
    107                 //我们按下了键盘,触发了 ServerKeyCharEvent 事件
    108                 RServer.ServerKeyChar();
    109 
    110                 if (k.KeyChar == 'k') {
    111                     //按下k,触发了 CloseCientEvent
    112                     RServer.CloseCient();
    113                 }
    114                 if (k.KeyChar == ' ') {
    115                     //按下空格,触发了 PauseClientEvent 事件
    116                     RServer.PauseClient();
    117                 }
    118                 if (k.KeyChar == 'l') {
    119                     //按下l,触发了 ListClientEvent 事件
    120                     RServer.ListClient();
    121                 }
    122                 if (k.KeyChar == 'x') {
    123                     //按下x,触发了 ServerShutdownEvent 事件
    124                     RServer.Shutdown();
    125                     break;
    126                 }
    127             }
    128         }
    129 
    130         private void onClientJoin(object sender, RemoteConsoleMessageEventArgs e)
    131         {
    132             Console.WriteLine("创建时间:{0}, 消息:{1}", ((TClientWaiter)sender).JoinDateTime, e.MessageText);
    133         }
    134     }
    135 
    136     public class TClientWaiter
    137     {
    138         public DateTime JoinDateTime;
    139         public bool running = true;
    140 
    141         //我们在client中也声明了一个事件(当然可以更多)
    142         public RemoteConsoleMessageDelegate clientJoinEvent;
    143 
    144         public Thread currentThread;
    145 
    146         public TClientWaiter()
    147         {
    148             JoinDateTime = DateTime.Now;
    149         }
    150 
    151         public TClientWaiter(TRemoteConsole server)
    152         {
    153             JoinDateTime = DateTime.Now;
    154 
    155             //在这里我们订阅了一系列的事件
    156             //所以上面的Server对象一旦有任何风吹草动,client都能知道
    157             server.ServerKeyCharEvent += this.onServerKeyChar;
    158             server.ServerShutdownEvent += this.onServerShutdown;
    159             server.CloseClientEvent += this.onCloseClient;
    160             server.PauseClientEvent += this.onPauseClient;
    161             server.ListClientEvent += this.onListClient;
    162         }
    163 
    164         //订阅了 ServerShutdown 事件,如果服务器要shutdown的话,我们有必要采取一些措施
    165         public void onServerShutdown(object sender, RemoteConsoleMessageEventArgs e)
    166         {
    167             Console.WriteLine("Server will shutdown");
    168         }
    169 
    170         //在上面说了,我们可以在Server端迭代List对象来关闭所有子线程
    171         //也可以通过事件机制来达到目的
    172         public void onCloseClient(object sender, RemoteConsoleMessageEventArgs e)
    173         {
    174             //这里我们就用事件来达到目的
    175             //一旦接收到 CloseClientEvent 事件(这是Server端发出的事件),所有的client线程退出
    176             try {
    177                 currentThread.Abort();
    178             } catch {}
    179             Console.WriteLine("{0}已退出,目前状态:{1}", currentThread.Name, currentThread.IsAlive);
    180         }
    181 
    182         public void onPauseClient(object sender, RemoteConsoleMessageEventArgs e)
    183         {
    184             this.running = !this.running;
    185             Console.WriteLine(this.running ? "继续" : "暂停");
    186         }
    187 
    188         public void onListClient(object sender, RemoteConsoleMessageEventArgs e)
    189         {
    190             Console.WriteLine("{0}状态:{1}", currentThread.Name, currentThread.IsAlive);
    191         }
    192 
    193         public void onServerKeyChar(object sender, RemoteConsoleMessageEventArgs e)
    194         {
    195             Console.WriteLine("从主程序传递过来的消息:{0}", e.MessageText);
    196         }
    197 
    198         public void connectionCreated()
    199         {
    200             currentThread = Thread.CurrentThread;
    201             
    202             //在这里我们触发了 clientJoinEvent 事件,在上面的 TRemoteConsole 对象中马上就能知道
    203             //依然要注意判断事件是否等于null
    204             if (this.clientJoinEvent != null) {
    205                 this.clientJoinEvent(thisnew RemoteConsoleMessageEventArgs("新的连接已建立"));
    206             } else {
    207                 Console.WriteLine("警告:没有定义任何处理 clientJoinEvent 事件的方法");
    208             }
    209             while(true)
    210             {
    211                 if (this.running)
    212                 {
    213                     Thread.Sleep(1000);
    214                     Console.WriteLine("{0}->{1}", currentThread.Name, DateTime.Now);
    215                 }
    216             }
    217         }
    218     }
    219 
    220     //自定义事件参数
    221     public class RemoteConsoleMessageEventArgs : EventArgs
    222     {
    223         private string message;
    224 
    225         public string MessageText
    226         {
    227             get {return message;}
    228         }
    229 
    230         public RemoteConsoleMessageEventArgs(string _msg)
    231         {
    232             message = _msg;
    233         }
    234     }
    235 }
  • 相关阅读:
    Python 内置函数 —— format
    命名集 —— 名字结构
    命名集 —— 名字结构
    存储与主板的外设接口
    存储与主板的外设接口
    验证码的认识
    验证码的认识
    windows 路径
    windows 路径
    极限的求法
  • 原文地址:https://www.cnblogs.com/ifan/p/1251753.html
Copyright © 2011-2022 走看看