快捷搜索:

Socket网络通信,自行完结高品质MVC

来源:http://www.zishawo.com 作者:注册送58元体验金app 人气:190 发布时间:2019-10-20
摘要:DNS类:DNS是多少个静态类,它从Internet域名系统(DNS)检索有关特定主机的新闻,在IPHostEntry类的实例中回到来自DNS查询的主机音讯。(GetHostName()找到本地系统的主机名,然后再用GetH
  1. DNS类:DNS是多少个静态类,它从Internet域名系统(DNS)检索有关特定主机的新闻,在IPHostEntry类的实例中回到来自DNS查询的主机音讯。(GetHostName()找到本地系统的主机名,然后再用GetHostByName()找到主机的IP地址)
  2. IPAddress类:包涵计算机在IP网络上的地点,首要用以提供网际合同(IP)地址。
  3. IPEndPoint类富含应用程序连接到主机上的服务所急需的主机和本土或远程端口音讯。首要用以将网络端点表示为IP地址和端口号。
  4. WebClient类:提供向UTiggoL标记的其余地点、Intranet或Internet能源发送数据以至从这一个能源接收数据的公家措施。
  5. WebRequest类:.Net Framework的伏乞/响应模型的画饼充饥基类,用于访谈Internet数据。使用该必要/响应模型的应用程序能够用合同不可以预知的主意从Internet央求数据。

连串化与反种类化

  种类化与反种类化这么些选二进制平日比json的好,ms版的BinaryFormatter 通用性强,但是她的质量、model的暗记写法等推测又要被喷了;找到Expression系列化,结果要么走的近乎于soap xml那风度翩翩套,想想算了:当地点法调用都以飞秒级的,io都以皮秒级其余,socket的贰遍就传这么传这么大学一年级堆,固然局域网也伤不起呀,想轻量化提高品质都难,自行达成七个简约的好了。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Serialize
  7 *文件名: SerializeUtil
  8 *版本号: V1.0.0.0
  9 *唯一标识:9e919430-465d-49a3-91be-b36ac682e283
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/22 13:17:36
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/22 13:17:36
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.RPC.Model;
 25 using System;
 26 using System.Collections.Generic;
 27 using System.Text;
 28 
 29 namespace SAEA.RPC.Serialize
 30 {
 31     /// <summary>
 32     /// rpc参数序列化处理
 33     /// </summary>
 34     public class ParamsSerializeUtil
 35     {
 36         /// <summary>
 37         /// len+data
 38         /// </summary>
 39         /// <param name="param"></param>
 40         /// <returns></returns>
 41         public static byte[] Serialize(object param)
 42         {
 43             List<byte> datas = new List<byte>();
 44 
 45             var len = 0;
 46             byte[] data = null;
 47 
 48             if (param == null)
 49             {
 50                 len = 0;
 51             }
 52             else
 53             {
 54                 if (param is string)
 55                 {
 56                     data = Encoding.UTF8.GetBytes((string)param);
 57                 }
 58                 else if (param is byte)
 59                 {
 60                     data = new byte[] { (byte)param };
 61                 }
 62                 else if (param is bool)
 63                 {
 64                     data = BitConverter.GetBytes((bool)param);
 65                 }
 66                 else if (param is short)
 67                 {
 68                     data = BitConverter.GetBytes((short)param);
 69                 }
 70                 else if (param is int)
 71                 {
 72                     data = BitConverter.GetBytes((int)param);
 73                 }
 74                 else if (param is long)
 75                 {
 76                     data = BitConverter.GetBytes((long)param);
 77                 }
 78                 else if (param is float)
 79                 {
 80                     data = BitConverter.GetBytes((float)param);
 81                 }
 82                 else if (param is double)
 83                 {
 84                     data = BitConverter.GetBytes((double)param);
 85                 }
 86                 else if (param is DateTime)
 87                 {
 88                     var str = "wl" + ((DateTime)param).Ticks;
 89                     data = Encoding.UTF8.GetBytes(str);
 90                 }
 91                 else if (param is byte[])
 92                 {
 93                     data = (byte[])param;
 94                 }
 95                 else
 96                 {
 97                     var type = param.GetType();
 98 
 99                     if (type.IsGenericType || type.IsArray)
100                     {
101                         data = SerializeList((System.Collections.IEnumerable)param);
102                     }
103                     else if (type.IsGenericTypeDefinition)
104                     {
105                         data = SerializeDic((System.Collections.IDictionary)param);
106                     }
107                     else if (type.IsClass)
108                     {
109                         var ps = type.GetProperties();
110 
111                         if (ps != null && ps.Length > 0)
112                         {
113                             List<object> clist = new List<object>();
114 
115                             foreach (var p in ps)
116                             {
117                                 clist.Add(p.GetValue(param));
118                             }
119                             data = Serialize(clist.ToArray());
120                         }
121                     }
122                 }
123                 len = data.Length;
124             }
125             datas.AddRange(BitConverter.GetBytes(len));
126             if (len > 0)
127             {
128                 datas.AddRange(data);
129             }
130             return datas.Count == 0 ? null : datas.ToArray();
131         }
132 
133 
134         private static byte[] SerializeList(System.Collections.IEnumerable param)
135         {
136             List<byte> list = new List<byte>();
137 
138             if (param != null)
139             {
140                 List<byte> slist = new List<byte>();
141 
142                 foreach (var item in param)
143                 {
144                     var type = item.GetType();
145 
146                     var ps = type.GetProperties();
147                     if (ps != null && ps.Length > 0)
148                     {
149                         List<object> clist = new List<object>();
150                         foreach (var p in ps)
151                         {
152                             clist.Add(p.GetValue(item));
153                         }
154 
155                         var clen = 0;
156 
157                         var cdata = Serialize(clist.ToArray());
158 
159                         if (cdata != null)
160                         {
161                             clen = cdata.Length;
162                         }
163 
164                         slist.AddRange(BitConverter.GetBytes(clen));
165                         slist.AddRange(cdata);
166                     }
167                 }
168 
169                 var len = 0;
170 
171                 if (slist.Count > 0)
172                 {
173                     len = slist.Count;
174                 }
175                 list.AddRange(BitConverter.GetBytes(len));
176                 list.AddRange(slist.ToArray());
177             }
178             return list.ToArray();
179         }
180 
181         private static byte[] SerializeDic(System.Collections.IDictionary param)
182         {
183             List<byte> list = new List<byte>();
184 
185             if (param != null && param.Count > 0)
186             {
187                 foreach (KeyValuePair item in param)
188                 {
189                     var type = item.GetType();
190                     var ps = type.GetProperties();
191                     if (ps != null && ps.Length > 0)
192                     {
193                         List<object> clist = new List<object>();
194                         foreach (var p in ps)
195                         {
196                             clist.Add(p.GetValue(item));
197                         }
198                         var clen = 0;
199 
200                         var cdata = Serialize(clist.ToArray());
201 
202                         if (cdata != null)
203                         {
204                             clen = cdata.Length;
205                         }
206 
207                         list.AddRange(BitConverter.GetBytes(clen));
208                         list.AddRange(cdata);
209                     }
210                 }
211             }
212             return list.ToArray();
213         }
214 
215         /// <summary>
216         /// len+data
217         /// </summary>
218         /// <param name="params"></param>
219         /// <returns></returns>
220         public static byte[] Serialize(params object[] @params)
221         {
222             List<byte> datas = new List<byte>();
223 
224             if (@params != null)
225             {
226                 foreach (var param in @params)
227                 {
228                     datas.AddRange(Serialize(param));
229                 }
230             }
231 
232             return datas.Count == 0 ? null : datas.ToArray();
233         }
234 
235         /// <summary>
236         /// 反序列化
237         /// </summary>
238         /// <param name="types"></param>
239         /// <param name="datas"></param>
240         /// <returns></returns>
241         public static object[] Deserialize(Type[] types, byte[] datas)
242         {
243             List<object> list = new List<object>();
244 
245             var len = 0;
246 
247             byte[] data = null;
248 
249             int offset = 0;
250 
251             for (int i = 0; i < types.Length; i++)
252             {
253                 list.Add(Deserialize(types[i], datas, ref offset));
254             }
255 
256             return list.ToArray();
257         }
258 
259         /// <summary>
260         /// 反序列化
261         /// </summary>
262         /// <param name="type"></param>
263         /// <param name="datas"></param>
264         /// <param name="offset"></param>
265         /// <returns></returns>
266         public static object Deserialize(Type type, byte[] datas, ref int offset)
267         {
268             dynamic obj = null;
269 
270             var len = 0;
271 
272             byte[] data = null;
273 
274             len = BitConverter.ToInt32(datas, offset);
275             offset += 4;
276             if (len > 0)
277             {
278                 data = new byte[len];
279                 Buffer.BlockCopy(datas, offset, data, 0, len);
280                 offset += len;
281 
282                 if (type == typeof(string))
283                 {
284                     obj = Encoding.UTF8.GetString(data);
285                 }
286                 else if (type == typeof(byte))
287                 {
288                     obj = (data);
289                 }
290                 else if (type == typeof(bool))
291                 {
292                     obj = (BitConverter.ToBoolean(data, 0));
293                 }
294                 else if (type == typeof(short))
295                 {
296                     obj = (BitConverter.ToInt16(data, 0));
297                 }
298                 else if (type == typeof(int))
299                 {
300                     obj = (BitConverter.ToInt32(data, 0));
301                 }
302                 else if (type == typeof(long))
303                 {
304                     obj = (BitConverter.ToInt64(data, 0));
305                 }
306                 else if (type == typeof(float))
307                 {
308                     obj = (BitConverter.ToSingle(data, 0));
309                 }
310                 else if (type == typeof(double))
311                 {
312                     obj = (BitConverter.ToDouble(data, 0));
313                 }
314                 else if (type == typeof(decimal))
315                 {
316                     obj = (BitConverter.ToDouble(data, 0));
317                 }
318                 else if (type == typeof(DateTime))
319                 {
320                     var dstr = Encoding.UTF8.GetString(data);
321                     var ticks = long.Parse(dstr.Substring(2));
322                     obj = (new DateTime(ticks));
323                 }
324                 else if (type == typeof(byte[]))
325                 {
326                     obj = (byte[])data;
327                 }
328                 else if (type.IsGenericType)
329                 {
330                     obj = DeserializeList(type, data);
331                 }
332                 else if (type.IsArray)
333                 {
334                     obj = DeserializeArray(type, data);
335                 }
336                 else if (type.IsGenericTypeDefinition)
337                 {
338                     obj = DeserializeDic(type, data);
339                 }
340                 else if (type.IsClass)
341                 {
342                     var instance = Activator.CreateInstance(type);
343 
344                     var ts = new List<Type>();
345 
346                     var ps = type.GetProperties();
347 
348                     if (ps != null)
349                     {
350                         foreach (var p in ps)
351                         {
352                             ts.Add(p.PropertyType);
353                         }
354                         var vas = Deserialize(ts.ToArray(), data);
355 
356                         for (int j = 0; j < ps.Length; j++)
357                         {
358                             try
359                             {
360                                 if (!ps[j].PropertyType.IsGenericType)
361                                 {
362                                     ps[j].SetValue(instance, Convert.ChangeType(vas[j], ps[j].PropertyType), null);
363                                 }
364                                 else
365                                 {
366                                     Type genericTypeDefinition = ps[j].PropertyType.GetGenericTypeDefinition();
367                                     if (genericTypeDefinition == typeof(Nullable<>))
368                                     {
369                                         ps[j].SetValue(instance, Convert.ChangeType(vas[j], Nullable.GetUnderlyingType(ps[j].PropertyType)), null);
370                                     }
371                                     else
372                                     {
373                                         //List<T>问题
374                                         ps[j].SetValue(instance, Convert.ChangeType(vas[j], ps[j].PropertyType), null);
375                                     }
376                                 }
377                             }
378                             catch (Exception ex)
379                             {
380                                 Console.WriteLine("反序列化不支持的类型:" + ex.Message);
381                             }
382                         }
383                     }
384                     obj = (instance);
385                 }
386                 else
387                 {
388                     throw new RPCPamarsException("ParamsSerializeUtil.Deserialize 未定义的类型:" + type.ToString());
389                 }
390 
391             }
392             return obj;
393         }
394 
395 
396         private static object DeserializeList(Type type, byte[] datas)
397         {
398             List<object> result = new List<object>();
399             var stype = type.GenericTypeArguments[0];
400 
401             var len = 0;
402             var offset = 0;
403             //容器大小
404             len = BitConverter.ToInt32(datas, offset);
405             offset += 4;
406             byte[] cdata = new byte[len];
407             Buffer.BlockCopy(datas, offset, cdata, 0, len);
408             offset += len;
409 
410             //子项内容
411             var slen = 0;
412             var soffset = 0;
413             while (soffset < len)
414             {
415                 slen = BitConverter.ToInt32(cdata, soffset);
416                 var sdata = new byte[slen + 4];
417                 Buffer.BlockCopy(cdata, soffset, sdata, 0, slen + 4);
418                 soffset += slen + 4;
419 
420                 if (slen > 0)
421                 {
422                     int lloffset = 0;
423                     var sobj = Deserialize(stype, sdata, ref lloffset);
424                     if (sobj != null)
425                         result.Add(sobj);
426                 }
427                 else
428                 {
429                     result.Add(null);
430                 }
431             }
432             return result;
433         }
434 
435         private static object DeserializeArray(Type type, byte[] datas)
436         {
437             var obj = DeserializeList(type, datas);
438 
439             if (obj == null) return null;
440 
441             var list = (obj as List<object>);
442 
443             return list.ToArray();
444         }
445 
446         private static object DeserializeDic(Type type, byte[] datas)
447         {
448             dynamic obj = null;
449 
450 
451 
452             return obj;
453         }
454     }
455 }

  实现的经过中,平时结构、类都还相比顺遂,不过数组、List、Dictionary照旧碰着了风流倜傥部分麻烦,暂且先放着,找到办法加以。真若是传那几个,如今先用其余连串化成byte[]来做……

因为委托的特质是引用类型,所以决定了信托是能够张开址传递。也正是说,委托是持续于大家系统代码中的列车。

1.8 管理职责中的十分

在职务中,处理非常和任何异步格局管理极度类似,借使能在所发出极度的线程中拍卖,那么毫无在别的地方处理。可是对于某些不行预料的要命,那么能够因此两种格局来管理。

能够因而访问task.Result品质来管理特别,因为访问这特本性的Get主意会使当前线程等待直到该职务成功,并将充分传播给当下线程,那样就足以由此try catch语句块来捕获卓殊。别的利用task.GetAwaiter().GetResult()措施和第使用task.Result临近,同样能够捕获非常。假若是要捕获三个职责中的分外错误,那么可以通过ContinueWith()艺术来拍卖。

切切实实哪些完结,演示代码如下所示。

static void Main(string[] args)
{
    Task<int> task;
    // 在主线程中调用 task.Result task中的异常信息会直接抛出到 主线程中
    try
    {
        task = Task.Run(() => TaskMethod("Task 1", 2));
        int result = task.Result;
        WriteLine($"结果为: {result}");
    }
    catch (Exception ex)
    {
        WriteLine($"异常被捕捉:{ex.Message}");
    }
    WriteLine("------------------------------------------------");
    WriteLine();

    // 同上 只是访问Result的方式不同
    try
    {
        task = Task.Run(() => TaskMethod("Task 2", 2));
        int result = task.GetAwaiter().GetResult();
        WriteLine($"结果为:{result}");
    }
    catch (Exception ex)
    {
        WriteLine($"异常被捕捉: {ex.Message}");
    }
    WriteLine("----------------------------------------------");
    WriteLine();

    var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
    var t2 = new Task<int>(() => TaskMethod("Task 4", 4));

    var complexTask = Task.WhenAll(t1, t2);
    // 通过ContinueWith TaskContinuationOptions.OnlyOnFaulted的方式 如果task出现异常 那么才会执行该方法
    var exceptionHandler = complexTask.ContinueWith(t => {
        WriteLine($"异常被捕捉:{t.Exception.Message}");
        foreach (var ex in t.Exception.InnerExceptions)
        {
            WriteLine($"-------------------------- {ex.Message}");
        }
    },TaskContinuationOptions.OnlyOnFaulted);

    t1.Start();
    t2.Start();

    ReadLine();
}

static int TaskMethod(string name, int seconds)
{
    WriteLine($"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}");

    Sleep(TimeSpan.FromSeconds(seconds));
    // 人为抛出一个异常
    throw new Exception("Boom!");
    return 42 * seconds;
}

运转结果如下所示,要求注意的是,假诺在ContinueWith()办法中抓获七个任务发生的特别,那么它的非常类型是AggregateException,具体的不胜音讯满含在InnerExceptions个中,要小心和InnerException区分。

图片 1

  最终F5跑起来看看效果:

Server:获取基础互连网Socket

前言

小李:“胖子,上头叫您对接笔者的数目好了未曾?”

胖子:“那是您的事,你都不提供数据源,作者咋接?”

小李:“你想要什么样的数据源?”

胖子:“小编想要二个调用不难题的!”

小李:“笔者这么些数据源是在linux平台使用docker封装发布的,webapi的什么样?”

胖子:“也行,那类型工期快用完了,你得提供api封装sdk,别的作者那边对品质有必要的!”

小李:“webapi多好,基于json种种平台都能接通,品质还不易的!”

胖子:“笔者只关怀作者的业务,不是本人的业务代码,多风姿罗曼蒂克行笔者都不想码,不然没按期达成算你的!别的用webapi到时候诉求量一大,到时候端口用完了,连接不了这锅也得你背!”

小李:“我@##¥%*#¥@#&##@……”

面对胖子这几个理由,小李心里面纵然20000只草泥马在跑马,不过项目或然要实现是不?别的胖子说的也客观!小李作为一个在C#下侵淫多年老司机,相当慢想出贰个办法——rpc!首先当然是选wcf,那几个巨硬的集团级产品在高速支付三巳了配置上坑爹了有个别,针对客商端的对接真的要命快。小李留意后生可畏切磋wcf service 开采眼下在linux下玩不了,心里面又是了后生可畏阵@##¥%*#¥@#&##@……

胖子:“小李纠缠啥,要不就弄个三方的搞一下算了,纵然出事了,你也许都早已离任了,怕啥……”

望着胖子风华正茂脸猥琐的表情,小李那是贰个气呀,就怪自已日常牛逼吹上天,那时候怎么好怂呢,龙腾虎跃咬牙:“你放心,误不了你的事!”。小李大器晚成边回复,心里面早先妄想着自行达成一个效果与利益简易,品质高效,使用简单的rpc了。

  上边小李与胖子的处境,在支付的时候也是出色案例,回到正题来:本身感觉rpc主纵然:调用方法及参数种类化、socket传输、调用方法及参数反类别化、映射到地头并使用与央浼同样流程回复客商端的日新月异套方案。此中关键点轻巧剖判首要有:体系化与反系列化、高质量tcp、远程方法反转、顾客端代码生成八个地方;tcp如故选用iocp好了,别的接着后生可畏一解析。

此间大家使用委托的BeginInvoke方法来拉开线程,举行异步调用。如上边代码所示,这里介绍了Action与Func的最基础的异步应用。

1.4 组合职责

在本节中,展示了职务之中一个有力的据守,那就是结合职分。通过结合职责可很好的叙说职分与职分之间的异步、同步关系,大大收缩了编程的难度。

结缘职责注重是透过task.ContinueWith()task.WhenAny()task.WhenAll()等和task.GetAwaiter().OnCompleted()格局来兑现。

在使用task.ContinueWith()主意时,要求小心它也可传递生机勃勃多元的枚举选项TaskContinuationOptions,该枚举选项和TaskCreationOptions就好像,其具体定义如下表所示。

成员名称 说明
AttachedToParent 如果延续为子任务,则指定将延续附加到任务层次结构中的父级。 只有当延续前面的任务也是子任务时,延续才可以是子任务。 默认情况下,子任务(即由外部任务创建的内部任务)将独立于其父任务执行。 可以使用 TaskContinuationOptions.AttachedToParent 选项以便将父任务和子任务同步。请注意,如果使用 DenyChildAttach 选项配置父任务,则子任务中的 AttachedToParent 选项不起作用,并且子任务将作为分离的子任务执行。有关更多信息,请参见Attached and Detached Child Tasks
DenyChildAttach 指定任何使用 TaskCreationOptions.AttachedToParent 选项创建,并尝试作为附加的子任务执行的子任务(即,由此延续创建的任何嵌套内部任务)都无法附加到父任务,会改成作为分离的子任务执行。 有关详细信息,请参阅附加和分离的子任务
ExecuteSynchronously 指定应同步执行延续任务。 指定此选项后,延续任务在导致前面的任务转换为其最终状态的相同线程上运行。如果在创建延续任务时已经完成前面的任务,则延续任务将在创建此延续任务的线程上运行。 如果前面任务的 CancellationTokenSource 已在一个 finally(在 Visual Basic 中为 Finally)块中释放,则使用此选项的延续任务将在该 finally 块中运行。 只应同步执行运行时间非常短的延续任务。由于任务以同步方式执行,因此无需调用诸如 Task.Wait 的方法来确保调用线程等待任务完成。
HideScheduler 指定由延续通过调用方法(如 Task.RunTask.ContinueWith)创建的任务将默认计划程序 (TaskScheduler.Default) 视为当前的计划程序,而不是正在运行该延续的计划程序。
LazyCancellation 在延续取消的情况下,防止延续的完成直到完成先前的任务。
LongRunning 指定延续将是长期运行的、粗粒度的操作。 它会向 TaskScheduler 提示,过度订阅可能是合理的。
None 如果未指定延续选项,应在执行延续任务时使用指定的默认行为。 延续任务在前面的任务完成后以异步方式运行,与前面任务最终的 Task.Status 属性值无关。 如果延续为子任务,则会将其创建为分离的嵌套任务。
NotOnCanceled 指定不应在延续任务前面的任务已取消的情况下安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.Canceled,则前面的任务会取消。 此选项对多任务延续无效。
NotOnFaulted 指定不应在延续任务前面的任务引发了未处理异常的情况下安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.Faulted,则前面的任务会引发未处理的异常。 此选项对多任务延续无效。
NotOnRanToCompletion 指定不应在延续任务前面的任务已完成运行的情况下安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.RanToCompletion,则前面的任务会运行直至完成。 此选项对多任务延续无效。
OnlyOnCanceled 指定只应在延续前面的任务已取消的情况下安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.Canceled,则前面的任务会取消。 此选项对多任务延续无效。
OnlyOnFaulted 指定只有在延续任务前面的任务引发了未处理异常的情况下才应安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.Faulted,则前面的任务会引发未处理的异常。OnlyOnFaulted 选项可保证前面任务中的 Task.Exception 属性不是 null。 你可以使用该属性来捕获异常,并确定导致任务出错的异常。 如果你不访问 Exception 属性,则不会处理异常。 此外,如果尝试访问已取消或出错的任务的 Result 属性,则会引发一个新异常。此选项对多任务延续无效。
OnlyOnRanToCompletion 指定只应在延续任务前面的任务已完成运行的情况下才安排延续任务。 如果前面任务完成的 Task.Status 属性是 TaskStatus.RanToCompletion,则前面的任务会运行直至完成。 此选项对多任务延续无效。
PreferFairness 提示 TaskScheduler 按任务计划的顺序安排任务,因此较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
RunContinuationsAsynchronously 指定应异步运行延续任务。 此选项优先于 TaskContinuationOptions.ExecuteSynchronously。

示范代码如下所示,使用ContinueWith()OnCompleted()方法结合了任务来运维,搭配不一致的TaskCreationOptionsTaskContinuationOptions来兑现差异的机能。

static void Main(string[] args)
{
    WriteLine($"主线程 线程 Id {CurrentThread.ManagedThreadId}");

    // 创建两个任务
    var firstTask = new Task<int>(() => TaskMethod("Frist Task",3));
    var secondTask = new Task<int>(()=> TaskMethod("Second Task",2));

    // 在默认的情况下 ContiueWith会在前面任务运行后再运行
    firstTask.ContinueWith(t => WriteLine($"第一次运行答案是 {t.Result}. 线程Id {CurrentThread.ManagedThreadId}. 是否为线程池线程: {CurrentThread.IsThreadPoolThread}"));

    // 启动任务
    firstTask.Start();
    secondTask.Start();

    Sleep(TimeSpan.FromSeconds(4));

    // 这里会紧接着 Second Task运行后运行, 但是由于添加了 OnlyOnRanToCompletion 和 ExecuteSynchronously 所以会由运行SecondTask的线程来 运行这个任务
    Task continuation = secondTask.ContinueWith(t => WriteLine($"第二次运行的答案是 {t.Result}. 线程Id {CurrentThread.ManagedThreadId}. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}"),TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously);

    // OnCompleted 是一个事件  当contiuation运行完成后 执行OnCompleted Action事件
    continuation.GetAwaiter().OnCompleted(() => WriteLine($"后继任务完成. 线程Id {CurrentThread.ManagedThreadId}. 是否为线程池线程 {CurrentThread.IsThreadPoolThread}"));

    Sleep(TimeSpan.FromSeconds(2));
    WriteLine();

    firstTask = new Task<int>(() => 
    {
        // 使用了TaskCreationOptions.AttachedToParent 将这个Task和父Task关联, 当这个Task没有结束时  父Task 状态为 WaitingForChildrenToComplete
        var innerTask = Task.Factory.StartNew(() => TaskMethod("Second Task",5), TaskCreationOptions.AttachedToParent);

        innerTask.ContinueWith(t => TaskMethod("Thrid Task", 2), TaskContinuationOptions.AttachedToParent);

        return TaskMethod("First Task",2);
    });

    firstTask.Start();

    // 检查firstTask线程状态  根据上面的分析 首先是  Running -> WatingForChildrenToComplete -> RanToCompletion
    while (! firstTask.IsCompleted)
    {
        WriteLine(firstTask.Status);

        Sleep(TimeSpan.FromSeconds(0.5));
    }

    WriteLine(firstTask.Status);

    Console.ReadLine();
}

static int TaskMethod(string name, int seconds)
{
    WriteLine($"任务 {name} 正在运行,线程池线程 Id {CurrentThread.ManagedThreadId},是否为线程池线程: {CurrentThread.IsThreadPoolThread}");

    Sleep(TimeSpan.FromSeconds(seconds));

    return 42 * seconds;
}

运作结果如下图所示,与预期结果新闯事物正在旭日初升律。当中使用了task.Status来打字与印刷职分运行的情景,对于task.Status的动静具体意思如下表所示。

成员名称 说明
Canceled 该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的 CancellationToken 发出了信号。 有关详细信息,请参阅任务取消
Created 该任务已初始化,但尚未被计划。
Faulted 由于未处理异常的原因而完成的任务。
RanToCompletion 已成功完成执行的任务。
Running 该任务正在运行,但尚未完成。
WaitingForActivation 该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。
WaitingForChildrenToComplete 该任务已完成执行,正在隐式等待附加的子任务完成。
WaitingToRun 该任务已被计划执行,但尚未开始执行。

图片 2

  设计的编码思路便是仿asp.net mvc,原因便是asp.net mvc成功发展了这么经过了异常的短的时间,有着多量的C#码农习于旧贯了那套精美的编码方式;至于spring mvc、spring boot那三个,站在使用者的角度来讲,光配置和注释都能敲死人,如要要说轻松飞速,asp.net mvc比她强多了,更别提ruby on rails。不扯远了,上边就按C#经文来。那么必要怀恋的标题有tcp、http、request、response、server、controller、actionresult、routetable等,下边就相继来化解那个标题。

        那是它能够以更加高的架空程度提供TCP服务的功底。浮今后网络数据的出殡和下葬和收受地点,是TcpClient使用NetworkStream网络流管理技巧,使得它读写多少进一步有利直观。TcpClient类专为顾客端设计,它为 TCP 互连网服务提供客商端连接。

测试

  至此多少个关键点都完成了,下边是vs2017的代码结构:

图片 3

  SAEA.RPCTest是测量试验项目,Provider为模拟服务端代码、RPCServiceProxy为生成器依照劳动端生成的客户端代码,Program.cs中是利用SAEA.RPC使用、测量试验代码:

  1 using SAEA.Commom;
  2 using SAEA.RPC.Provider;
  3 using SAEA.RPCTest.Consumer;
  4 //using SAEA.RPCTest.Consumer;
  5 using System;
  6 using System.Diagnostics;
  7 using System.Threading;
  8 using System.Threading.Tasks;
  9 
 10 namespace SAEA.RPCTest
 11 {
 12     class Program
 13     {
 14         static void Main(string[] args)
 15         {
 16             ConsoleHelper.WriteLine($"SAEA.RPC功能测试: {Environment.NewLine}   p 启动rpc provider{Environment.NewLine}   c 启动rpc consumer{Environment.NewLine}   g 启动rpc consumer代码生成器");
 17 
 18             var inputStr = ConsoleHelper.ReadLine();
 19 
 20             if (string.IsNullOrEmpty(inputStr))
 21             {
 22                 inputStr = "p";
 23             }
 24 
 25             if (inputStr == "c")
 26             {
 27                 ConsoleHelper.WriteLine("开始Consumer测试!");
 28                 ConsumerInit();
 29                 ConsoleHelper.WriteLine("回车结束!");
 30                 ConsoleHelper.ReadLine();
 31             }
 32             else if (inputStr == "a")
 33             {
 34                 ProviderInit();
 35                 ConsoleHelper.WriteLine("回车开始Consumer测试!");
 36                 ConsoleHelper.ReadLine();
 37                 ConsumerInit();
 38                 ConsoleHelper.WriteLine("回车结束!");
 39                 ConsoleHelper.ReadLine();
 40             }
 41             else if (inputStr == "g")
 42             {
 43                 ConsoleHelper.WriteLine("正在代码生成中...");
 44                 Generate();
 45                 ConsoleHelper.WriteLine("代码生成完毕,回车结束!");
 46                 ConsoleHelper.ReadLine();
 47             }
 48             else
 49             {
 50                 ProviderInit();
 51                 ConsoleHelper.WriteLine("回车结束!");
 52                 ConsoleHelper.ReadLine();
 53             }
 54         }
 55 
 56 
 57         static void ProviderInit()
 58         {
 59             ConsoleHelper.Title = "SAEA.RPC.Provider";
 60             ConsoleHelper.WriteLine("Provider正在启动HelloService。。。");
 61             var sp = new ServiceProvider(new Type[] { typeof(Provider.HelloService) });
 62             sp.Start();
 63             ConsoleHelper.WriteLine("Provider就绪!");
 64         }
 65 
 66         static void Generate()
 67         {
 68             RPC.Generater.CodeGnerater.Generate(PathHelper.Current, "SAEA.RPCTest");
 69         }
 70 
 71         static void ConsumerInit()
 72         {
 73             ConsoleHelper.Title = "SAEA.RPC.Consumer";
 74 
 75             var url = "rpc://127.0.0.1:39654";
 76 
 77             ConsoleHelper.WriteLine($"Consumer正在连接到{url}...");
 78 
 79             RPCServiceProxy cp = new RPCServiceProxy(url);
 80 
 81             ConsoleHelper.WriteLine("Consumer连接成功");
 82 
 83             ConsoleHelper.WriteLine("HelloService/Hello:" + cp.HelloService.Hello());
 84             ConsoleHelper.WriteLine("HelloService/Plus:" + cp.HelloService.Plus(1, 9));
 85             ConsoleHelper.WriteLine("HelloService/Update/UserName:" + cp.HelloService.Update(new Consumer.Model.UserInfo() { ID = 1, UserName = "yswenli" }).UserName);
 86             ConsoleHelper.WriteLine("HelloService/GetGroupInfo/Creator.UserName:" + cp.HelloService.GetGroupInfo(1).Creator.UserName);
 87             ConsoleHelper.WriteLine("HelloService/SendData:" + System.Text.Encoding.UTF8.GetString(cp.HelloService.SendData(System.Text.Encoding.UTF8.GetBytes("Hello Data"))));
 88             ConsoleHelper.WriteLine("回车启动性能测试!");
 89 
 90             ConsoleHelper.ReadLine();
 91 
 92             #region 性能测试
 93 
 94             Stopwatch sw = new Stopwatch();
 95 
 96             int count = 1000000;
 97 
 98             ConsoleHelper.WriteLine($"{count} 次实体传输调用测试中...");
 99 
100             var ui = new Consumer.Model.UserInfo() { ID = 1, UserName = "yswenli" };
101 
102             sw.Start();
103 
104             for (int i = 0; i < count; i++)
105             {
106                 cp.HelloService.Update(ui);
107             }
108             ConsoleHelper.WriteLine($"实体传输:{count * 1000 / sw.ElapsedMilliseconds} 次/秒");
109 
110             sw.Stop();
111 
112             #endregion
113 
114 
115 
116         }
117     }
118 }

  在命令行上校SAEA.RPCTest发表输入dotnet pulish -r win7-x64后运转exe如下:

图片 4

迄今一个使用方便、高品质rpc就初始实现了。

转发请标注本文来源:
越多内容应接star/fork小编的github:
假若开采本文有怎样难题和其余建议,也随即接待调换~

我们来看地方的代码,父类中增加了四个异步委托的调用函数,接下去,我们就足以在承接该类的子类中,随手翻开线程了。

我水平有限,假诺不当款待各位争论指正!

本来想趁待业时期的日子读完《Multithreading with C# 库克book Second Edition》那本书,并且享受做的相关笔记;可是由于小编近年来专门的职业规划和人体原因,恐怕近日都不曾时间来更新那么些种类,没办法达成几天如日方升更。请大家多多包罗!可是小编必定将那几个序列全部更新实现的!多谢我们的支撑!

图片 5

  1. void Connect(IPEndPoint):使用钦点的中远间距网络节点将客商端连接到远程TCP主机。
    1 IPAddress ipAddress = Dns.Resolve(Dns.GetHostName()).AddressList(0);//获取IP地址
    2 IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 60000);//设置端口
    3 TcpClient tcpClientA = new TcpClient(ipLocalEndPoint);//创建客户端
    

长间距方法反转

  远程方法反转就是将吸取到的数据一定到本地的靶子方法上,借使代码生成、参数使用使用泛型反系列化,理论上是足以晋级部分本性的;然而另生气勃勃方面写服务专门的职业,意气风发边编写定义结构文件、还后生可畏边生成服务代码,本地点法都以阿秒级、相对io的快慢来说,若是为了这一点品质升高,在行使的时候揣度又是意气风发阵@##¥%*#¥@#&##@……,所以如故选择反射、拆箱吧。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Common
  7 *文件名: RPCInovker
  8 *版本号: V1.0.0.0
  9 *唯一标识:289c03b9-3910-4e15-8072-93243507689c
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/17 14:11:30
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/17 14:11:30
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.RPC.Model;
 25 using SAEA.RPC.Net;
 26 using SAEA.RPC.Serialize;
 27 using SAEA.Sockets.Interface;
 28 using System;
 29 using System.Linq;
 30 using System.Reflection;
 31 
 32 namespace SAEA.RPC.Common
 33 {
 34     /// <summary>
 35     /// RPC将远程调用反转到本地服务
 36     /// </summary>
 37     public class RPCReversal
 38     {
 39         static object _locker = new object();
 40         
 41 
 42         /// <summary>
 43         /// 执行方法
 44         /// </summary>
 45         /// <param name="action"></param>
 46         /// <param name="obj"></param>
 47         /// <param name="args"></param>
 48         /// <returns></returns>
 49         private static object ReversalMethod(MethodInfo action, object obj, object[] args)
 50         {
 51             object result = null;
 52             try
 53             {
 54                 var @params = action.GetParameters();
 55 
 56                 if (@params != null && @params.Length > 0)
 57                 {
 58                     result = action.Invoke(obj, args);
 59                 }
 60                 else
 61                 {
 62                     result = action.Invoke(obj, null);
 63                 }
 64             }
 65             catch (Exception ex)
 66             {
 67                 throw new RPCPamarsException($"{obj}/{action.Name},出现异常:{ex.Message}", ex);
 68             }
 69             return result;
 70         }
 71 
 72 
 73         public static object Reversal(IUserToken userToken, string serviceName, string methodName, object[] inputs)
 74         {
 75             lock (_locker)
 76             {
 77                 try
 78                 {
 79                     var serviceInfo = RPCMapping.Get(serviceName, methodName);
 80 
 81                     if (serviceInfo == null)
 82                     {
 83                         throw new RPCNotFundException($"当前请求找不到:{serviceName}/{methodName}", null);
 84                     }
 85 
 86                     var nargs = new object[] { userToken, serviceName, methodName, inputs };
 87 
 88                     if (serviceInfo.FilterAtrrs != null && serviceInfo.FilterAtrrs.Count > 0)
 89                     {
 90                         foreach (var arr in serviceInfo.FilterAtrrs)
 91                         {
 92                             var goOn = (bool)arr.GetType().GetMethod("OnActionExecuting").Invoke(arr, nargs.ToArray());
 93 
 94                             if (!goOn)
 95                             {
 96                                 return new RPCNotFundException("当前逻辑已被拦截!", null);
 97                             }
 98                         }
 99                     }
100 
101                     if (serviceInfo.ActionFilterAtrrs != null && serviceInfo.ActionFilterAtrrs.Count > 0)
102                     {
103                         foreach (var arr in serviceInfo.ActionFilterAtrrs)
104                         {
105                             var goOn = (bool)arr.GetType().GetMethod("OnActionExecuting").Invoke(arr, nargs.ToArray());
106 
107                             if (!goOn)
108                             {
109                                 return new RPCNotFundException("当前逻辑已被拦截!", null);
110                             }
111                         }
112                     }
113 
114                     var result = ReversalMethod(serviceInfo.Mothd, serviceInfo.Instance, inputs);
115 
116                     nargs = new object[] { userToken, serviceName, methodName, inputs, result };
117 
118                     if (serviceInfo.FilterAtrrs != null && serviceInfo.FilterAtrrs.Count > 0)
119                     {
120                         foreach (var arr in serviceInfo.FilterAtrrs)
121                         {
122                             arr.GetType().GetMethod("OnActionExecuted").Invoke(arr, nargs);
123                         }
124                     }
125 
126                     if (serviceInfo.ActionFilterAtrrs != null && serviceInfo.ActionFilterAtrrs.Count > 0)
127                     {
128                         foreach (var arr in serviceInfo.FilterAtrrs)
129                         {
130                             arr.GetType().GetMethod("OnActionExecuted").Invoke(arr, nargs);
131                         }
132                     }
133                     return result;
134                 }
135                 catch (Exception ex)
136                 {
137                     if (ex.Message.Contains("找不到此rpc方法"))
138                     {
139                         return new RPCNotFundException("找不到此rpc方法", ex);
140                     }
141                     else
142                     {
143                         return new RPCNotFundException("找不到此rpc方法", ex);
144                     }
145                 }
146             }
147         }
148 
149         /// <summary>
150         /// 反转到具体的方法上
151         /// </summary>
152         /// <param name="userToken"></param>
153         /// <param name="msg"></param>
154         /// <returns></returns>
155         public static byte[] Reversal(IUserToken userToken, RSocketMsg msg)
156         {
157             byte[] result = null;
158             try
159             {
160                 object[] inputs = null;
161 
162                 if (msg.Data != null)
163                 {
164                     var ptypes = RPCMapping.Get(msg.ServiceName, msg.MethodName).Pamars.Values.ToArray();
165 
166                     inputs = ParamsSerializeUtil.Deserialize(ptypes, msg.Data);
167                 }
168 
169                 var r = Reversal(userToken, msg.ServiceName, msg.MethodName, inputs);
170 
171                 if (r != null)
172                 {
173                     return ParamsSerializeUtil.Serialize(r);
174                 }
175             }
176             catch (Exception ex)
177             {
178                 throw new RPCPamarsException("RPCInovker.Invoke error:" + ex.Message, ex);
179             }
180             return result;
181 
182         }
183     }
184 }


  至此,二个精简、高效的WebApi就从头产生了!

 3. void Connect(string,int):将客户端连接到钦点主机上的钦点端口。

客户端代码生成

  为了有帮忙顾客选用rpc,所以有rpc相关的代码在客商端那必然是越少越好,假如光服务端方便,客商端估量又要@##¥%*#¥@#&##@……,所以将某个rpc相关代码生成好,客商端透明调用是必需的。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Generater
  7 *文件名: CodeGnerater
  8 *版本号: V1.0.0.0
  9 *唯一标识:59ba5e2a-2fd0-444b-a260-ab68c726d7ee
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/17 18:30:57
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/17 18:30:57
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.RPC.Common;
 25 using SAEA.RPC.Model;
 26 using System;
 27 using System.Collections.Generic;
 28 using System.IO;
 29 using System.Linq;
 30 using System.Reflection;
 31 using System.Text;
 32 
 33 namespace SAEA.RPC.Generater
 34 {
 35     /// <summary>
 36     /// 代码生成器
 37     /// </summary>
 38     public static class CodeGnerater
 39     {
 40         static string space4 = "    ";
 41 
 42         /// <summary>
 43         /// 获取指定数量的空格
 44         /// </summary>
 45         /// <param name="num"></param>
 46         /// <returns></returns>
 47         static string GetSpace(int num = 1)
 48         {
 49             var sb = new StringBuilder();
 50 
 51             for (int i = 0; i < num; i++)
 52             {
 53                 sb.Append(space4);
 54             }
 55 
 56             return sb.ToString();
 57         }
 58 
 59         /// <summary>
 60         /// 获取变量名
 61         /// </summary>
 62         /// <param name="str"></param>
 63         /// <returns></returns>
 64         static string GetSuffixStr(string str)
 65         {
 66             return "_" + str.Substring(0, 1).ToLower() + str.Substring(1);
 67         }
 68 
 69         /// <summary>
 70         /// 生成代码头部
 71         /// </summary>
 72         /// <returns></returns>
 73         static string Header(params string[] usings)
 74         {
 75             var sb = new StringBuilder();
 76             sb.AppendLine("/*******");
 77             sb.AppendLine($"*此代码为SAEA.RPCGenerater生成 {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
 78             sb.AppendLine("*******/" + Environment.NewLine);
 79             sb.AppendLine("using System;");
 80             if (usings != null)
 81             {
 82                 foreach (var u in usings)
 83                 {
 84                     sb.AppendLine(u);
 85                 }
 86             }
 87             return sb.ToString();
 88         }
 89 
 90         static string _proxyStr;
 91 
 92         static List<string> _serviceStrs = new List<string>();
 93 
 94         static Dictionary<string, string> _modelStrs = new Dictionary<string, string>();
 95 
 96         /// <summary>
 97         /// 生成代理代码
 98         /// </summary>
 99         /// <param name="spaceName"></param>
100         internal static void GenerateProxy(string spaceName)
101         {
102             StringBuilder csStr = new StringBuilder();
103             csStr.AppendLine(Header("using SAEA.RPC.Consumer;", $"using {spaceName}.Consumer.Model;", $"using {spaceName}.Consumer.Service;"));
104             csStr.AppendLine($"namespace {spaceName}.Consumer");
105             csStr.AppendLine("{");
106             csStr.AppendLine($"{GetSpace(1)}public class RPCServiceProxy");
107             csStr.AppendLine(GetSpace(1) + "{");
108 
109             csStr.AppendLine(GetSpace(2) + "ServiceConsumer _serviceConsumer;");
110             csStr.AppendLine(GetSpace(2) + "public RPCServiceProxy(string uri = "rpc://127.0.0.1:39654") : this(new Uri(uri)){}");
111             csStr.AppendLine(GetSpace(2) + "public RPCServiceProxy(Uri uri)");
112             csStr.AppendLine(GetSpace(2) + "{");
113 
114             csStr.AppendLine(GetSpace(3) + "_serviceConsumer = new ServiceConsumer(uri);");
115 
116             var names = RPCMapping.GetServiceNames();
117 
118             if (names != null)
119             {
120                 foreach (var name in names)
121                 {
122                     csStr.AppendLine(GetSpace(3) + GetSuffixStr(name) + $" = new {name}(_serviceConsumer);");
123                 }
124             }
125             csStr.AppendLine(GetSpace(2) + "}");
126 
127             if (names != null)
128             {
129                 foreach (var name in names)
130                 {
131                     var suffixStr = GetSuffixStr(name);
132 
133                     csStr.AppendLine(GetSpace(2) + $"{name} {suffixStr};");
134                     csStr.AppendLine(GetSpace(2) + $"public {name} {name}");
135                     csStr.AppendLine(GetSpace(2) + "{");
136                     csStr.AppendLine($"{GetSpace(3)} get{{ return {suffixStr}; }}");
137                     csStr.AppendLine(GetSpace(2) + "}");
138 
139                     var list = RPCMapping.GetAll(name);
140                     if (list != null)
141                     {
142                         GenerateService(spaceName, name, list);
143                     }
144                 }
145             }
146 
147             csStr.AppendLine(GetSpace(1) + "}");
148             csStr.AppendLine("}");
149             _proxyStr = csStr.ToString();
150         }
151         /// <summary>
152         /// 生成调用服务代码
153         /// </summary>
154         /// <param name="spaceName"></param>
155         /// <param name="serviceName"></param>
156         /// <param name="methods"></param>
157         internal static void GenerateService(string spaceName, string serviceName, Dictionary<string, ServiceInfo> methods)
158         {
159             StringBuilder csStr = new StringBuilder();
160             csStr.AppendLine($"namespace {spaceName}.Consumer.Service");
161             csStr.AppendLine("{");
162             csStr.AppendLine($"{GetSpace(1)}public class {serviceName}");
163             csStr.AppendLine(GetSpace(1) + "{");
164             csStr.AppendLine(GetSpace(2) + "ServiceConsumer _serviceConsumer;");
165             csStr.AppendLine(GetSpace(2) + $"public {serviceName}(ServiceConsumer serviceConsumer)");
166             csStr.AppendLine(GetSpace(2) + "{");
167             csStr.AppendLine(GetSpace(3) + "_serviceConsumer = serviceConsumer;");
168             csStr.AppendLine(GetSpace(2) + "}");
169 
170             foreach (var item in methods)
171             {
172                 var rtype = item.Value.Mothd.ReturnType;
173 
174                 if (rtype != null)
175                 {
176                     if (!_modelStrs.ContainsKey($"{spaceName}.Consumer.Model.{rtype.Name}"))
177                     {
178                         GenerateModel(spaceName, rtype);
179                     }
180                 }
181 
182                 var argsStr = new StringBuilder();
183 
184                 var argsInput = new StringBuilder();
185 
186                 if (item.Value.Pamars != null)
187                 {
188                     int i = 0;
189                     foreach (var arg in item.Value.Pamars)
190                     {
191                         i++;
192                         argsStr.Append(arg.Value.Name);
193                         argsStr.Append(" ");
194                         argsStr.Append(arg.Key);
195                         if (i < item.Value.Pamars.Count)
196                             argsStr.Append(", ");
197 
198                         if (arg.Value != null && arg.Value.IsClass)
199                         {
200                             if (!_modelStrs.ContainsKey($"{spaceName}.Consumer.Model.{arg.Value.Name}"))
201                             {
202                                 GenerateModel(spaceName, arg.Value);
203                             }
204                         }
205 
206                         argsInput.Append(", ");
207                         argsInput.Append(arg.Key);
208                     }
209                 }
210 
211                 csStr.AppendLine(GetSpace(2) + $"public {rtype.Name} {item.Key}({argsStr.ToString()})");
212                 csStr.AppendLine(GetSpace(2) + "{");
213                 csStr.AppendLine(GetSpace(3) + $"return _serviceConsumer.RemoteCall<{rtype.Name}>("{serviceName}", "{item.Key}"{argsInput.ToString()});");
214                 csStr.AppendLine(GetSpace(2) + "}");
215 
216 
217             }
218 
219             csStr.AppendLine(GetSpace(1) + "}");
220             csStr.AppendLine("}");
221             _serviceStrs.Add(csStr.ToString());
222         }
223 
224         /// <summary>
225         /// 生成实体代码
226         /// </summary>
227         /// <typeparam name="T"></typeparam>
228         /// <param name="t"></param>
229         /// <returns></returns>
230         internal static void GenerateModel(string spaceName, Type type)
231         {
232             if (!IsModel(type)) return;
233             StringBuilder csStr = new StringBuilder();
234             csStr.AppendLine($"namespace {spaceName}.Consumer.Model");
235             csStr.AppendLine("{");
236             csStr.AppendLine($"{GetSpace(1)}public class {type.Name}");
237             csStr.AppendLine(GetSpace(1) + "{");
238             var ps = type.GetProperties();
239             foreach (var p in ps)
240             {
241                 csStr.AppendLine($"{GetSpace(2)}public {p.PropertyType.Name} {p.Name}");
242                 csStr.AppendLine(GetSpace(2) + "{");
243                 csStr.AppendLine(GetSpace(3) + "get;set;");
244                 csStr.AppendLine(GetSpace(2) + "}");
245             }
246             csStr.AppendLine(GetSpace(1) + "}");
247             csStr.AppendLine("}");
248             _modelStrs.Add($"{spaceName}.Consumer.Model.{type.Name}", csStr.ToString());
249         }
250 
251         /// <summary>
252         /// 是否是实体
253         /// </summary>
254         /// <param name="type"></param>
255         /// <returns></returns>
256         internal static bool IsModel(Type type)
257         {
258             if (type.IsArray || type.IsSealed || !type.IsClass)
259             {
260                 return false;
261             }
262             return true;
263         }
264 
265         /// <summary>
266         /// 生成客户端C#代码文件
267         /// </summary>
268         /// <param name="folder"></param>
269         /// <param name="spaceName"></param>
270         public static void Generate(string folder, string spaceName)
271         {
272             RPCMapping.RegistAll();
273 
274             GenerateProxy(spaceName);
275 
276             var filePath = Path.Combine(folder, "RPCServiceProxy.cs");
277 
278             StringBuilder sb = new StringBuilder();
279 
280             sb.AppendLine(_proxyStr);
281 
282             if (_serviceStrs != null && _serviceStrs.Count > 0)
283             {
284                 foreach (var serviceStr in _serviceStrs)
285                 {
286                     sb.AppendLine(serviceStr);
287                 }
288             }
289 
290             if (_modelStrs != null && _modelStrs.Count > 0)
291             {
292                 foreach (var entry in _modelStrs)
293                 {
294                     sb.AppendLine(entry.Value);
295                 }
296             }
297 
298             if (File.Exists(filePath))
299                 File.Delete(filePath);
300 
301             File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8);
302         }
303 
304 
305     }
306 }

  无论在服务端根据数据将长途调用反转当地点法、依然生成顾客端代码的长河都离不开服务协会的主题素材。假若是依照结构文件来拍卖,则先要编写结构文件;服务端码农活不重事相当少呀?文书档案没发你啊?啥锅都往那边甩……此处省略三万字。其他繁荣昌盛种方式正是临近web mvc选用约定形式,写完服务工作代码后,再自动生成结构并缓存在内部存款和储蓄器里。

  1 /****************************************************************************
  2 *Copyright (c) 2018 Microsoft All Rights Reserved.
  3 *CLR版本: 4.0.30319.42000
  4 *机器名称:WENLI-PC
  5 *公司名称:Microsoft
  6 *命名空间:SAEA.RPC.Provider
  7 *文件名: ServiceTable
  8 *版本号: V1.0.0.0
  9 *唯一标识:e95f1d0b-f172-49c7-b75f-67f333504260
 10 *当前的用户域:WENLI-PC
 11 *创建人: yswenli
 12 *电子邮箱:wenguoli_520@qq.com
 13 *创建时间:2018/5/16 17:46:34
 14 *描述:
 15 *
 16 *=====================================================================
 17 *修改标记
 18 *修改时间:2018/5/16 17:46:34
 19 *修改人: yswenli
 20 *版本号: V1.0.0.0
 21 *描述:
 22 *
 23 *****************************************************************************/
 24 using SAEA.Commom;
 25 using SAEA.RPC.Model;
 26 using System;
 27 using System.Collections.Concurrent;
 28 using System.Collections.Generic;
 29 using System.Diagnostics;
 30 using System.Linq;
 31 using System.Reflection;
 32 
 33 namespace SAEA.RPC.Common
 34 {
 35     /// <summary>
 36     /// 服务类缓存表
 37     /// md5+ServiceInfo反射结果
 38     /// </summary>
 39     internal static class RPCMapping
 40     {
 41         static object _locker = new object();
 42 
 43         static HashMap<string, string, ServiceInfo> _serviceMap = new HashMap<string, string, ServiceInfo>();
 44 
 45         /// <summary>
 46         /// 本地注册RPC服务缓存
 47         /// </summary>
 48         public static HashMap<string, string, ServiceInfo> ServiceMap
 49         {
 50             get
 51             {
 52                 return _serviceMap;
 53             }
 54         }
 55 
 56         /// <summary>
 57         /// 本地注册RPC服务
 58         /// </summary>
 59         /// <param name="type"></param>
 60         public static void Regist(Type type)
 61         {
 62             lock (_locker)
 63             {
 64                 var serviceName = type.Name;
 65 
 66                 if (IsRPCService(type))
 67                 {
 68                     var methods = type.GetMethods();
 69 
 70                     var rms = GetRPCMehod(methods);
 71 
 72                     if (rms.Count > 0)
 73                     {
 74                         foreach (var m in rms)
 75                         {
 76                             var serviceInfo = new ServiceInfo()
 77                             {
 78                                 Type = type,
 79                                 Instance = Activator.CreateInstance(type),
 80                                 Mothd = m,
 81                                 Pamars = m.GetParameters().ToDic()
 82                             };
 83 
 84                             List<object> iAttrs = null;
 85 
 86                             //类上面的过滤
 87                             var attrs = type.GetCustomAttributes(true);
 88 
 89                             if (attrs != null && attrs.Length > 0)
 90                             {
 91                                 var classAttrs = attrs.Where(b => b.GetType().BaseType.Name == "ActionFilterAttribute").ToList();
 92 
 93                                 if (classAttrs != null && classAttrs.Count > 0)
 94 
 95                                     iAttrs = classAttrs;
 96 
 97                             }
 98 
 99                             serviceInfo.FilterAtrrs = iAttrs;
100 
101                             //action上面的过滤
102                             var actionAttrs = m.GetCustomAttributes(true);
103 
104                             if (actionAttrs != null)
105                             {
106                                 var filterAttrs = attrs.Where(b => b.GetType().BaseType.Name == "ActionFilterAttribute").ToList();
107 
108                                 if (filterAttrs != null && filterAttrs.Count > 0)
109 
110                                     serviceInfo.ActionFilterAtrrs = filterAttrs;
111                             }
112 
113                             _serviceMap.Set(serviceName, m.Name, serviceInfo);
114                         }
115                     }
116                 }
117             }
118         }
119 
120         /// <summary>
121         /// 本地注册RPC服务
122         /// 若为空,则默认全部注册带有ServiceAttribute的服务
123         /// </summary>
124         /// <param name="types"></param>
125         public static void Regists(params Type[] types)
126         {
127             if (types != null)
128                 foreach (var type in types)
129                 {
130                     Regist(type);
131                 }
132             else
133                 RegistAll();
134         }
135         /// <summary>
136         /// 全部注册带有ServiceAttribute的服务
137         /// </summary>
138         public static void RegistAll()
139         {
140             StackTrace ss = new StackTrace(true);
141             MethodBase mb = ss.GetFrame(2).GetMethod();
142             var space = mb.DeclaringType.Namespace;
143             var tt = mb.DeclaringType.Assembly.GetTypes();
144             Regists(tt);
145         }
146 
147         /// <summary>
148         /// 判断类是否是RPCService
149         /// </summary>
150         /// <param name="type"></param>
151         /// <returns></returns>
152         public static bool IsRPCService(Type type)
153         {
154             var isService = false;
155             var cAttrs = type.GetCustomAttributes(true);
156             if (cAttrs != null)
157             {
158                 foreach (var cAttr in cAttrs)
159                 {
160                     if (cAttr is RPCServiceAttribute)
161                     {
162                         isService = true;
163                         break;
164                     }
165                 }
166             }
167             return isService;
168         }
169 
170         /// <summary>
171         /// 获取RPC方法集合
172         /// </summary>
173         /// <param name="mInfos"></param>
174         /// <returns></returns>
175         public static List<MethodInfo> GetRPCMehod(MethodInfo[] mInfos)
176         {
177             List<MethodInfo> result = new List<MethodInfo>();
178             if (mInfos != null)
179             {
180                 var isRPC = false;
181                 foreach (var method in mInfos)
182                 {
183                     if (method.IsAbstract || method.IsConstructor || method.IsFamily || method.IsPrivate || method.IsStatic || method.IsVirtual)
184                     {
185                         break;
186                     }
187                     
188                     isRPC = true;
189                     var attrs = method.GetCustomAttributes(true);
190                     if (attrs != null)
191                     {
192                         foreach (var attr in attrs)
193                         {
194                             if (attr is NoRpcAttribute)
195                             {
196                                 isRPC = false;
197                                 break;
198                             }
199                         }
200                     }
201                     if (isRPC)
202                     {
203                         result.Add(method);
204                     }
205                 }
206             }
207             return result;
208         }
209 
210         /// <summary>
211         /// 转换成字典
212         /// </summary>
213         /// <param name="parameterInfos"></param>
214         /// <returns></returns>
215         public static Dictionary<string, Type> ToDic(this ParameterInfo[] parameterInfos)
216         {
217             if (parameterInfos == null) return null;
218 
219             Dictionary<string, Type> dic = new Dictionary<string, Type>();
220 
221             foreach (var p in parameterInfos)
222             {
223                 dic.Add(p.Name, p.ParameterType);
224             }
225 
226             return dic;
227         }
228 
229 
230         /// <summary>
231         /// 获取缓存内容
232         /// </summary>
233         /// <param name="serviceName"></param>
234         /// <param name="methodName"></param>
235         /// <returns></returns>
236         public static ServiceInfo Get(string serviceName, string methodName)
237         {
238             lock (_locker)
239             {
240                 return _serviceMap.Get(serviceName, methodName);
241             }
242         }
243 
244         /// <summary>
245         /// 获取缓存内容
246         /// </summary>
247         /// <returns></returns>
248         public static List<string> GetServiceNames()
249         {
250             lock (_locker)
251             {
252                 return _serviceMap.GetHashIDs();
253             }
254         }
255         /// <summary>
256         /// 获取服务的全部信息
257         /// </summary>
258         /// <param name="serviceName"></param>
259         /// <returns></returns>
260         public static Dictionary<string, ServiceInfo> GetAll(string serviceName)
261         {
262             lock (_locker)
263             {
264                 return _serviceMap.GetAll(serviceName);
265             }
266         }
267 
268 
269 
270     }
271 }

大器晚成经必要公共委托,能够利用反射的点子来调用。

1.6 将EAP情势调换为职务

在上几章中有关系,通过BackgroundWorker类经过事件的方法落到实处的异步,我们叫它EAP格局。那么哪些将EAP格局转变为天职吗?比较轻巧,大家只要求通过TaskCompletionSource类,就可以将EAP方式转变为职务。

示范代码如下所示。

static void Main(string[] args)
{
    var tcs = new TaskCompletionSource<int>();

    var worker = new BackgroundWorker();
    worker.DoWork += (sender, eventArgs) =>
    {
        eventArgs.Result = TaskMethod("后台工作", 5);
    };

    // 通过此方法 将EAP模式转换为 任务
    worker.RunWorkerCompleted += (sender, eventArgs) =>
    {
        if (eventArgs.Error != null)
        {
            tcs.SetException(eventArgs.Error);
        }
        else if (eventArgs.Cancelled)
        {
            tcs.SetCanceled();
        }
        else
        {
            tcs.SetResult((int)eventArgs.Result);
        }
    };

    worker.RunWorkerAsync();

    // 调用结果
    int result = tcs.Task.Result;

    WriteLine($"结果是:{result}");

    ReadLine();
}

static int TaskMethod(string name, int seconds)
{
    WriteLine($"任务{name}运行在线程{CurrentThread.ManagedThreadId}上. 是否为线程池线程{CurrentThread.IsThreadPoolThread}");

    Sleep(TimeSpan.FromSeconds(seconds));

    return 42 * seconds;
}

运作结果如下图所示。

图片 6

  经过剖析后http的内容格式其实正是字符回车分隔,再加上部分预订生成的相间符bound达成的。

1 TcpClient tcpClient = new TcpClient();             //创建TcpClient对象实例
2 tcpClient.Connect("www.baidu.com",4088);         //尝试与远程主机相连
3 NetworkStream stream=tcpClient.GetStream();      //获取网络传输流

这么,你技巧称之为[Developer]。

  • 1.1 简介
  • 1.2 创造任务
  • 1.3 使用职分实践基本的操作
  • 1.4 组合任务
  • 1.5 将APM情势转变为职务
  • 1.6 将EAP格局转变为天职
  • 1.7 实现打消选项
  • 1.8 管理任务中的万分
  • 1.9 互相运营职责
  • 1.10 使用TaskScheduler配置职责执行
  • 参照书籍
  • 作者水平有限,假如不当招待各位研讨指正!

图片 7图片 8

(2)使用远程主机的主机名和端口号创立TcpClient,此构造函数将自动尝试贰个总是。

我们先从刚介绍过的嘱托的线程应用提起。

1.7 达成撤除选项

在TAP格局中,达成打消选项和事先的异步形式同样,都以应用CancellationToken来贯彻,不过分歧的是Task构造函数同意传入四个CancellationToken,进而在职责实际运营从前撤废它。

亲自去做代码如下所示。

static void Main(string[] args)
{
    var cts = new CancellationTokenSource();
    // new Task时  可以传入一个 CancellationToken对象  可以在线程创建时  变取消任务
    var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token);
    WriteLine(longTask.Status);
    cts.Cancel();
    WriteLine(longTask.Status);
    WriteLine("第一个任务在运行前被取消.");

    // 同样的 可以通过CancellationToken对象 取消正在运行的任务
    cts = new CancellationTokenSource();
    longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token);
    longTask.Start();

    for (int i = 0; i < 5; i++)
    {
        Sleep(TimeSpan.FromSeconds(0.5));
        WriteLine(longTask.Status);
    }
    cts.Cancel();
    for (int i = 0; i < 5; i++)
    {
        Sleep(TimeSpan.FromSeconds(0.5));
        WriteLine(longTask.Status);
    }

    WriteLine($"这个任务已完成,结果为{longTask.Result}");

    ReadLine();
}

static int TaskMethod(string name, int seconds, CancellationToken token)
{
    WriteLine($"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}");

    for (int i = 0; i < seconds; i++)
    {
        Sleep(TimeSpan.FromSeconds(1));
        if (token.IsCancellationRequested)
        {
            return -1;
        }
    }

    return 42 * seconds;
}

运营结果如下图所示,这里须求小心的是,假若是在职分奉行早先撤除了职务,那么它的末尾状态是Canceled。假如是在试行进度中收回职责,那么它的情景是RanCompletion

图片 9

 

        .Net中的TcpListener主要意义是监视TCP端口上顾客端的央求,通过绑定本机IP地址和呼应端口创制TcpListener对象实例,并由Start方法运营侦听;当TcpListener侦听到用户端的一连后,通过AcceptTcpClient方法接受传入的连天须要并创办TcpClient以拍卖诉求,大概通过AcceptSocket方法接受传入的连年诉求并成立Socket以拍卖供给。

因为委托是援用类型,所以能够被[址传递]。函数是不得以被传送的。

参照书籍

正文首要参照他事他说加以考察了以下几本书,在这里对那些作者表示真心的感激,多谢您们为.Net的扩大所做的贡献!

  1. 《CLR via C#》
  2. 《C# in Depth Third Edition》
  3. 《Essential C# 6.0》
  4. 《Multithreading with C# Cookbook Second Edition》
  5. 《C#三十二线程编制程序实战》

源码下载点击链接 亲自去做源码下载

  四、HttpServer:以此正是承先启后webapi的容器;有些人讲不是有IIS和Apache么?本身想说的是:有self-host方便么?有不需求安装,没有要求配置、随意高质量开跑好么?asp.net core里面都有了这一个,没这几个就未有逼格....(此处省略一万字),前边还探究tcp、http那么些本来无法少了

    1. void Bind(IPEndPoint localEP):绑定地址,使Socket与一个本地终节点相关联。
    2. Void Connect(IPEndPoint ip):创建连接
    3. Void Listen(int backlog):将Socket置于侦听状态, backlog最多可连接数。
    4. Int Receive(byte[] buffer):接收数据
    5. Int Receive (byte[] buffer,ref IPEndPoint ip):从钦点地点接收数据
    6. Int Send(byte[] buffer):发送数据
    7. Int Send To(byte[] buffer,ref IPEndPoint remoteIP):向内定地方发送数据
    8. Void Shutdown(SocketShutdown how):关闭套接字,how钦定不在允许施行的操作
Action a1 = () => { };
Func<int> f1 = () => { return 1; };//必须写 return 1;

目录

  纯粹干净单码,无任何晦涩内容,假诺对mvc有必然了然的,那个大概可以NoNotes,接下去正是按asp.net mvc命名方式,写个测量试验webapi看看动静,首先依然测量检验项目结构图:

图片 10

诸如能够跨类调用,跨程序集调用等等。而这种用法,便是信托的为主选取。

1.9 并行运营义务

本节中至关心注重要介绍了四个主意的使用,叁个是等待组中全体职务都实行落成的Task.WhenAll()主意,另一个是要是组中二个措施实践完结都实施的Task.WhenAny()方法。

实际应用,如下演示代码所示。

static void Main(string[] args)
{
    // 第一种方式 通过Task.WhenAll 等待所有任务运行完成
    var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
    var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));

    // 当firstTask 和 secondTask 运行完成后 才执行 whenAllTask的ContinueWith
    var whenAllTask = Task.WhenAll(firstTask, secondTask);
    whenAllTask.ContinueWith(t => WriteLine($"第一个任务答案为{t.Result[0]},第二个任务答案为{t.Result[1]}"), TaskContinuationOptions.OnlyOnRanToCompletion);

    firstTask.Start();
    secondTask.Start();

    Sleep(TimeSpan.FromSeconds(4));

    // 使用WhenAny方法  只要列表中有一个任务完成 那么该方法就会取出那个完成的任务
    var tasks = new List<Task<int>>();
    for (int i = 0; i < 4; i++)
    {
        int counter = 1;
        var task = new Task<int>(() => TaskMethod($"Task {counter}",counter));
        tasks.Add(task);
        task.Start();
    }

    while (tasks.Count > 0)
    {
        var completedTask = Task.WhenAny(tasks).Result;
        tasks.Remove(completedTask);
        WriteLine($"一个任务已经完成,结果为 {completedTask.Result}");
    }

    ReadLine();
}

static int TaskMethod(string name, int seconds)
{
    WriteLine($"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}");

    Sleep(TimeSpan.FromSeconds(seconds));
    return 42 * seconds;
}

运作结果如下图所示。

图片 11

  HomeController里面按asp.net mvc的习贯来编排代码:

 1 //建立TCP监听器TcpListener对象。
 2  TcpListener tl=new TcpListener(端口号);
 3 //启动监听器
 4 tl.Start();
 5 //用监听器获取连接进来的套接字(Socket)
 6 Socket s=myList.AcceptSocket();
 7 //通过Socket的Receive方法获取客户端发送的数据
 8 byte [] result=new byte[1024];
 9 int k=s.Receive(result);
10 //通过Socket的Send方法向客户端发送数据
11 byte[] st=System.Text.Encoding.Default.GetBytes(“text”);
12 s.Send(st);
13 //在通讯结束后,需要释放资源结束监听
14 s.Close();
15 tl.Stop();
class BaseDelegateSyntax
{ 
    public void AsyncLoad(Action action)
    {

    }
    public void AsyncLoad(Action action, Action callback)
    {
        IAsyncResult result = action.BeginInvoke((iar) =>
        {
            callback();
        }, null);
    }
    public void AsyncLoad<T>(Action<T> action, T para, Action callback)
    {
        IAsyncResult result = action.BeginInvoke(para, (iar) =>
        {
            callback();
        }, null);
    }
    public void AsyncLoad<T, R>(Func<T, R> action, T para, Action<R> callback)
    {
        IAsyncResult result = action.BeginInvoke(para, (iar) =>
        {
            var res = action.EndInvoke(iar);
            callback(res);
        }, null);
    }
}

1.2 创制义务

在本节中,重即使自己要作为范例死守规则了什么样制造三个职责。其根本接纳了System.Threading.Tasks取名空间下的Task类。该类能够被实例化并且提供了蒸蒸日上组静态方法,能够方便迅速的创始职分。

在底下实例代码中,分别延时了两种广泛的天职创制方式,何况创办职分是足以钦点职分创造的选项,进而达到最优的创造方式。

TaskCreationOptions中一同有7个枚举,枚举是足以运用|运算符组合定义的。其枚举如下表所示。

成员名称 说明
AttachedToParent 指定将任务附加到任务层次结构中的某个父级。 默认情况下,子任务(即由外部任务创建的内部任务)将独立于其父任务执行。 可以使用 TaskContinuationOptions.AttachedToParent 选项以便将父任务和子任务同步。请注意,如果使用 DenyChildAttach 选项配置父任务,则子任务中的 AttachedToParent 选项不起作用,并且子任务将作为分离的子任务执行。有关详细信息,请参阅附加和分离的子任务
DenyChildAttach 指定任何尝试作为附加的子任务执行(即,使用 AttachedToParent 选项创建)的子任务都无法附加到父任务,会改成作为分离的子任务执行。 有关详细信息,请参阅附加和分离的子任务
HideScheduler 防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 Default 当前计划程序。
LongRunning 指定任务将是长时间运行的、粗粒度的操作,涉及比细化的系统更少、更大的组件。 它会向 TaskScheduler 提示,过度订阅可能是合理的。 可以通过过度订阅创建比可用硬件线程数更多的线程。 它还将提示任务计划程序:该任务需要附加线程,以使任务不阻塞本地线程池队列中其他线程或工作项的向前推动。
None 指定应使用默认行为。
PreferFairness 提示 TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
RunContinuationsAsynchronously 强制异步执行添加到当前任务的延续任务。请注意,RunContinuationsAsynchronously 成员在以 .NET Framework 4.6 开头的 TaskCreationOptions 枚举中可用。
static void Main(string[] args)
{
    // 使用构造方法创建任务
    var t1 = new Task(() => TaskMethod("Task 1"));
    var t2 = new Task(() => TaskMethod("Task 2"));

    // 需要手动启动
    t2.Start();
    t1.Start();

    // 使用Task.Run 方法启动任务  不需要手动启动
    Task.Run(() => TaskMethod("Task 3"));

    // 使用 Task.Factory.StartNew方法 启动任务 实际上就是Task.Run
    Task.Factory.StartNew(() => TaskMethod("Task 4"));

    // 在StartNew的基础上 添加 TaskCreationOptions.LongRunning 告诉 Factory该任务需要长时间运行
    // 那么它就会可能会创建一个 非线程池线程来执行任务  
    Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);

    ReadLine();
}

static void TaskMethod(string name)
{
    WriteLine($"任务 {name} 运行,线程 id {CurrentThread.ManagedThreadId}. 是否为线程池线程: {CurrentThread.IsThreadPoolThread}.");
}

运作结果如下图所示。

图片 12

 

        在System.Net.Sockets命名空间下的UdpClient类,提供越来越直观的轻易使用的品质和章程,进而减弱UDP编程的难度。使用UdpClient时,连接的客商端须求首发送三个音讯给服务器,服务器才干和顾客端通信。

运作结果如下:


 1 /****************************************************************************
 2 *Copyright (c) 2018 Microsoft All Rights Reserved.
 3 *CLR版本: 4.0.30319.42000
 4 *机器名称:WENLI-PC
 5 *公司名称:Microsoft
 6 *命名空间:SAEA.WebAPI.Mvc
 7 *文件名: Controller
 8 *版本号: V1.0.0.0
 9 *唯一标识:a303db7d-f83c-4c49-9804-032ec2236232
10 *当前的用户域:WENLI-PC
11 *创建人: yswenli
12 *电子邮箱:wenguoli_520@qq.com
13 *创建时间:2018/4/10 13:58:08
14 *描述:
15 *
16 *=====================================================================
17 *修改标记
18 *修改时间:2018/4/10 13:58:08
19 *修改人: yswenli
20 *版本号: V1.0.0.0
21 *描述:
22 *
23 *****************************************************************************/
24 
25 using SAEA.WebAPI.Http;
26 
27 namespace SAEA.WebAPI.Mvc
28 {
29     /// <summary>
30     /// WebApi控制器
31     /// </summary>
32     public abstract class Controller
33     {
34         public HttpContext HttpContext { get; set; }
35 
36         /// <summary>
37         /// 返回Json
38         /// </summary>
39         /// <param name="data"></param>
40         /// <returns></returns>
41         protected JsonResult Json(object data)
42         {
43             return new JsonResult(data);
44         }
45         /// <summary>
46         /// 自定义内容
47         /// </summary>
48         /// <param name="data"></param>
49         /// <returns></returns>
50         protected ContentResult Content(string data)
51         {
52             return new ContentResult(data);
53         }
54 
55 
56         /// <summary>
57         /// 小文件
58         /// </summary>
59         /// <param name="filePath"></param>
60         /// <returns></returns>
61         protected FileResult File(string filePath)
62         {
63             return new FileResult(filePath);
64         }
65 
66         /// <summary>
67         /// 空结果
68         /// </summary>
69         /// <returns></returns>
70         protected EmptyResult Empty()
71         {
72             return new EmptyResult();
73         }
74     }
75 }

(1)成立叁个TcpClient,并调用多个可用的Connect()方法之如火如荼。

末端笔者会继续写事件,音讯,反射等语法,敬请期望。

1.10 使用TaskScheduler配置义务执行

Task中,担负职分调治是TaskScheduler对象,FCL提供了三个派生自TaskScheduler的类型:线程池职务调治器(Thread Pool Task Scheduler)生机勃勃块上下文职责调解器(Synchronization Scheduler)。暗中同意意况下全体应用程序都使用线程池义务调解器,但是在UI组件中,不使用线程池中的线程,幸免跨线程更新UI,供给采纳同步上下文职分调整器。能够通过进行TaskSchedulerFromCurrentSynchronizationContext()静态方法来获得对联合上下文任务调解器的援用。

亲自去做程序如下所示,为了延时伙同上下文职分调节器,我们本次利用WPF来创立项目。

MainWindow.xaml 代码如下所示。

<Window x:Class="Recipe9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Recipe9"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock Name="ContentTextBlock" HorizontalAlignment="Left" Margin="44,134,0,0" VerticalAlignment="Top" Width="425" Height="40"/>
        <Button Content="Sync" HorizontalAlignment="Left" Margin="45,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonSync_Click"/>
        <Button Content="Async" HorizontalAlignment="Left" Margin="165,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonAsync_Click"/>
        <Button Content="Async OK" HorizontalAlignment="Left" Margin="285,190,0,0" VerticalAlignment="Top" Width="75" Click="ButtonAsyncOK_Click"/>
    </Grid>
</Window>

MainWindow.xaml.cs 代码如下所示。

/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    // 同步执行 计算密集任务 导致UI线程阻塞
    private void ButtonSync_Click(object sender, RoutedEventArgs e)
    {
        ContentTextBlock.Text = string.Empty;

        try
        {
            string result = TaskMethod().Result;
            ContentTextBlock.Text = result;
        }
        catch (Exception ex)
        {
            ContentTextBlock.Text = ex.InnerException.Message;
        }
    }

    // 异步的方式来执行 计算密集任务 UI线程不会阻塞 但是 不能跨线程更新UI 所以会有异常
    private void ButtonAsync_Click(object sender, RoutedEventArgs e)
    {
        ContentTextBlock.Text = string.Empty;
        Mouse.OverrideCursor = Cursors.Wait;

        Task<string> task = TaskMethod();
        task.ContinueWith(t => {
            ContentTextBlock.Text = t.Exception.InnerException.Message;
            Mouse.OverrideCursor = null;
        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
    }

    // 通过 异步 和 FromCurrentSynchronizationContext方法 创建了线程同步的上下文  没有跨线程更新UI 
    private void ButtonAsyncOK_Click(object sender, RoutedEventArgs e)
    {
        ContentTextBlock.Text = string.Empty;
        Mouse.OverrideCursor = Cursors.Wait;
        Task<string> task = TaskMethod(TaskScheduler.FromCurrentSynchronizationContext());

        task.ContinueWith(t => Mouse.OverrideCursor = null,
            CancellationToken.None,
            TaskContinuationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext());
    }

    Task<string> TaskMethod()
    {
        return TaskMethod(TaskScheduler.Default);
    }

    Task<string> TaskMethod(TaskScheduler scheduler)
    {
        Task delay = Task.Delay(TimeSpan.FromSeconds(5));

        return delay.ContinueWith(t =>
        {
            string str = $"任务运行在{CurrentThread.ManagedThreadId}上. 是否为线程池线程:{CurrentThread.IsThreadPoolThread}";

            Console.WriteLine(str);

            ContentTextBlock.Text = str;
            return str;
        }, scheduler);
    }
}

运维结果如下所示,从左至右依次单击开关,前多个按键将会掀起那一个。
图片 13

具体新闻如下所示。

图片 14

 

  1. BeginRead():从NetworkStream起初一步读取
  2. BeginWrite():初始向流异步写入
  3. Close():关闭NetworkStream
  4. EndRead():处理异步读取截止
  5. EndWrite():管理异步写入甘休
  6. Flush():刷新流中的多少
  7. Read():从流中读取
  8. ReadByte():从流中读取多少个字节,并将流内的职务向前推动五个字节。达到最后,重临-1。
  9. Write():将数据写入NetworkStream
  10. WriteByte():将三个字节写入流内的此时此刻职责,并将流内的职责向前拉动二个字节。

第朝气蓬勃,大家成立父类代码如下:

1.5 将APM情势转变为天职

在头里的章节中,介绍了基于IAsyncResult接口落成了BeginXXXX/EndXXXX方法的就叫APM情势。APM方式特别古老,那么什么样将它转变为TAP方式吧?对于广泛的三种APM形式异步义务,我们日常选取接纳Task.Factory.FromAsync()格局来促成将APM模式转换为TAP模式

身体力行代码如下所示,比较简单不作过多介绍。

static void Main(string[] args)
{
    int threadId;
    AsynchronousTask d = Test;
    IncompatibleAsychronousTask e = Test;

    // 使用 Task.Factory.FromAsync方法 转换为Task
    WriteLine("Option 1");
    Task<string> task = Task<string>.Factory.FromAsync(d.BeginInvoke("异步任务线程", CallBack, "委托异步调用"), d.EndInvoke);

    task.ContinueWith(t => WriteLine($"回调函数执行完毕,现在运行续接函数!结果:{t.Result}"));

    while (!task.IsCompleted)
    {
        WriteLine(task.Status);
        Sleep(TimeSpan.FromSeconds(0.5));
    }
    WriteLine(task.Status);
    Sleep(TimeSpan.FromSeconds(1));

    WriteLine("----------------------------------------------");
    WriteLine();

    // 使用 Task.Factory.FromAsync重载方法 转换为Task
    WriteLine("Option 2");

    task = Task<string>.Factory.FromAsync(d.BeginInvoke,d.EndInvoke,"异步任务线程","委托异步调用");

    task.ContinueWith(t => WriteLine($"任务完成,现在运行续接函数!结果:{t.Result}"));

    while (!task.IsCompleted)
    {
        WriteLine(task.Status);
        Sleep(TimeSpan.FromSeconds(0.5));
    }
    WriteLine(task.Status);
    Sleep(TimeSpan.FromSeconds(1));

    WriteLine("----------------------------------------------");
    WriteLine();

    // 同样可以使用 FromAsync方法 将 BeginInvoke 转换为 IAsyncResult 最后转换为 Task
    WriteLine("Option 3");

    IAsyncResult ar = e.BeginInvoke(out threadId, CallBack, "委托异步调用");
    task = Task<string>.Factory.FromAsync(ar, _ => e.EndInvoke(out threadId, ar));

    task.ContinueWith(t => WriteLine($"任务完成,现在运行续接函数!结果:{t.Result},线程Id {threadId}"));

    while (!task.IsCompleted)
    {
        WriteLine(task.Status);
        Sleep(TimeSpan.FromSeconds(0.5));
    }
    WriteLine(task.Status);

    ReadLine();
}

delegate string AsynchronousTask(string threadName);
delegate string IncompatibleAsychronousTask(out int threadId);

static void CallBack(IAsyncResult ar)
{
    WriteLine("开始运行回调函数...");
    WriteLine($"传递给回调函数的状态{ar.AsyncState}");
    WriteLine($"是否为线程池线程:{CurrentThread.IsThreadPoolThread}");
    WriteLine($"线程池工作线程Id:{CurrentThread.ManagedThreadId}");
}

static string Test(string threadName)
{
    WriteLine("开始运行...");
    WriteLine($"是否为线程池线程:{CurrentThread.IsThreadPoolThread}");
    Sleep(TimeSpan.FromSeconds(2));

    CurrentThread.Name = threadName;
    return $"线程名:{CurrentThread.Name}";
}

static string Test(out int threadId)
{
    WriteLine("开始运行...");
    WriteLine($"是否为线程池线程:{CurrentThread.IsThreadPoolThread}");
    Sleep(TimeSpan.FromSeconds(2));

    threadId = CurrentThread.ManagedThreadId;
    return $"线程池线程工作Id是:{threadId}";
}

运转结果如下图所示。

图片 15

 1         public void GetRequest(byte[] data, Action<string> onUnpackage)
 2         {
 3             lock (_locker)
 4             {
 5                 var str = Encoding.UTF8.GetString(data);
 6 
 7                 var index = str.IndexOf(ENDSTR);
 8 
 9                 if (index > -1)
10                 {
11                     var s = str.Substring(0, index);
12 
13                     _result.Append(s);
14 
15                     onUnpackage.Invoke(_result.ToString());
16 
17                     _result.Clear();
18 
19                     if (str.Length > index + 4)
20                     {
21                         _result.Append(str.Substring(index + 4));
22                     }
23                 }
24                 else
25                 {
26                     _result.Append(str);
27                 }
28             }
29         }

利用Socket编写UdpClient

当您传递函数的时候,其实是无名传递了贰个信托的地点。

1.3 使用职务试行基本的操作

在本节中,使用职分实施基本的操作,并且得到职务试行到位后的结果值。本节内容比较轻便,在那不做过多介绍。

躬行实践代码如下,在主线程中要获取结果值,常用的秘技正是探问task.Result品质,如果职分线程还没试行达成,那么会阻塞主线程,直到线程奉行完。要是职务线程实践完成,那么将一贯获得运算的结果值。

Task 3中,使用了task.Status来打字与印刷线程的事态,线程每一种情状的实际意思,即将下焕发青大年中介绍。

static void Main(string[] args)
{
    // 直接执行方法 作为参照
    TaskMethod("主线程任务");

    // 访问 Result属性 达到运行结果
    Task<int> task = CreateTask("Task 1");
    task.Start();
    int result = task.Result;
    WriteLine($"运算结果: {result}");

    // 使用当前线程,同步执行任务
    task = CreateTask("Task 2");
    task.RunSynchronously();
    result = task.Result;
    WriteLine($"运算结果:{result}");

    // 通过循环等待 获取运行结果
    task = CreateTask("Task 3");
    WriteLine(task.Status);
    task.Start();

    while (!task.IsCompleted)
    {
        WriteLine(task.Status);
        Sleep(TimeSpan.FromSeconds(0.5));
    }

    WriteLine(task.Status);
    result = task.Result;
    WriteLine($"运算结果:{result}");

    Console.ReadLine();
}

static Task<int> CreateTask(string name)
{
    return new Task<int>(() => TaskMethod(name));
}

static int TaskMethod(string name)
{
    WriteLine($"{name} 运行在线程 {CurrentThread.ManagedThreadId}上. 是否为线程池线程 {CurrentThread.IsThreadPoolThread}");

    Sleep(TimeSpan.FromSeconds(2));

    return 42;
}

运营结果如下,可以见到Task 1Task 2均是运作在主线程上,并不是线程池线程。

图片 16

   五、Controller:为了落实类似于mvc的成效Controller那几个盛名的自然不能够少了,其在C#中动用非常微量的代码就能够达成

TCP与UDP的区别

佚名委托固然减差一点代码,但依旧须求大家和好去表明委托。全数,仍然是能够再简写一点吗?

本系列首页链接:[C#二十多线程编制程序种类(风度翩翩)- 简单介绍 ]

Socket网络通信,自行完结高品质MVC。 

(1)创设贰个TcpClient,并调用3个可用Connect方法之龙精虎猛。

有没有以为,这么些复杂的变量极度像一个函数的定义。

1.1 简介

在事先的多少个章节中,就线程的运用和三十二线程相关的剧情开展了介绍。因为线程涉及到异步、同步、极度传递等难点,所以在类型中使用二十四线程的代价是相比高昂的,须要编制大批量的代码来达到科学和强壮性。

为了缓和那样有个别的主题材料,在.Net Framework 4.0中引进了叁个有关一步操作的API。它叫做职分并行库(Task Parallel Library)。然后在.Net Framwork 4.5中对它进行了一线的精耕细作,本文的案例都是用风尚版本的TPL库,并且大家仍可以够使用C# 5.0的新特征await/async来简化TAP编制程序,当然那是从此才介绍的。

TPL内部选取了线程池,不过效能越来越高。在把线程归还回线程池早前,它会在同一线程中相继实施多少Task,那样防止了有的小职务上下文切换浪费时间片的主题材料。

职务是指标,在那之中封装了以异步方式实行的干活,可是委托也是包裹了代码的对象。职务和嘱托的差别在于,委托是同步的,而职责是异步的。

在本章中,我们将议和论哪些利用TPL库来进展任务之间的组成同步,怎样将残留的APM和EAP形式转变为TPL格局等等。

  当然不是,非常是在dnc2.0早就格外强大的此时,完全能够自行设计大器晚成套简洁、高效的webapi框架!提及自动写风度翩翩套框架,比比较多码农们就恐怕会想到开垦职业量难以想像,事实真的这么么?java因为开源众多,比很多对mvc稍有打探的都得以拿那一个拿那一个拼出八个自已的mvc框架;而面临日渐苍劲的dnc,本人以为C#素有不需求东挪西凑这么辛勤,完全能够依照自已的要求轻便连忙的写出二个来,不服就开干!

动用UdpClient类落成UDP公约编制程序

Action与Func是泛型委托,各帮衬十五个入参变量。下边代码为多个入参的概念,多参数由此及彼。

图片 17

(1)制造服务器端:

信托的定义

  六、ActionResult:是mvc里面针对reponse结果开展了贰个http格式的卷入,本人根本实现了ContentResult、JsonResult、FileResult多个,至于别的的在WebAPI里基本上用不到。

        使用C#进展互联网编制程序时,日常都亟需用到System.Net命名空间、System.Net.Sockets命名空间和System.Net.Mail命名空间;

假设函数是援引类型,那么那几个函数只要没被内部存储器回收,就能够被调用。假设是public函数恐怕是public static函数,那么它能胜过的东西就更加的多了。

  增添二个LogAtrribute打字与印刷一些剧情:

  1. AcceptSocket/AcceptTcpClient:接受挂起的接连央浼
  2. BeginAcceptSocket/BeginAcceptTcpClient:起先三个异步操作来经受一个流传的接连尝试
  3. Start:带头侦听传入的连年乞求
  4. Stop:关闭侦听

结语

  在MVC的合计里面ActionFilterAtrribute的这一个AOP设计也一直伴随左右,比方记日志、黑名单、权限、验证、限流等等功用,所以路由的时候也会缓存那几个。至此一些关键性的地点都早就弄的大半了,为了更加好的摸底上边说的那些,下边是vs2017中项指标构造截图:

本文由js9905com金沙网站发布于注册送58元体验金app,转载请注明出处:Socket网络通信,自行完结高品质MVC

关键词:

上一篇:引用类型对象的深拷贝,数据结构

下一篇:没有了

最火资讯