一个更好一点的主线程与子线程之间通信的做法

  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 }
posted @ 2008-07-25 22:22  ifanxp  阅读(2344)  评论(0编辑  收藏  举报