• 从无到有实现.net协程(三)


    在前一篇中,还存在一个问题,当没有请求进来时,线程仍然会轮询执行,这样造成了CPU资源的浪费,因此,需要进一步改进,实现仅当有请求进入时,才启动线程。

    还是先实现协程容器

      1 /// <summary>
      2     /// 基于自动多线程的协程容器实现
      3     /// </summary>
      4     public class CoroutineContainerMultipleAuto : ICoroutineContainer
      5     {
      6 
      7         /// <summary>
      8         /// 存储多线程协程单元项
      9         /// </summary>
     10         private List<MultipleItem> _multipleItems = new List<MultipleItem>();
     11 
     12         /// <summary>
     13         /// 设定的线程数
     14         /// </summary>
     15         private int _threadCount;
     16         /// <summary>
     17         /// 错误处理
     18         /// </summary>
     19         private Action<ICoroutineUnit,Exception> _errorHandle;
     20         public CoroutineContainerMultipleAuto(int threadCount,Action<ICoroutineUnit,Exception> errorHandle)
     21         {
     22             _threadCount = threadCount;
     23             _errorHandle = errorHandle;
     24         }
     25         public void Register(ICoroutineUnit unit)
     26         {
     27             //随机分摊请求
     28             Random random = new Random();
     29             var index = random.Next(0, _threadCount);
     30 
     31             lock (_multipleItems[index].AddUnits)
     32             {
     33                 _multipleItems[index].AddUnits.Add(new UnitItem() { Unit = unit, UnitResult = null });
     34                 //要求协程处理线程启动
     35                 _multipleItems[index].Run();
     36             }
     37 
     38         }
     39         /// <summary>
     40         /// 容器启动
     41         /// 这里并不会真正启动线程
     42         /// </summary>
     43         public void Run()
     44         {
     45             for (var index = 0; index <= _threadCount - 1; index++)
     46             {
     47                 var multipleItem = new MultipleItem() { Units = new List<UnitItem>(), AddUnits = new List<UnitItem>(), ErrorHandle=_errorHandle };
     48                 _multipleItems.Add(multipleItem);
     49 
     50             }
     51 
     52 
     53 
     54         }
     55 
     56 
     57         private class UnitItem
     58         {
     59             public ICoroutineUnit Unit { get; set; }
     60             public IEnumerator<Task> UnitResult { get; set; }
     61         }
     62 
     63         /// <summary>
     64         /// 多线程协程单元项
     65         /// </summary>
     66         private class MultipleItem
     67         {
     68             public List<UnitItem> Units
     69             {
     70                 get; set;
     71             }
     72 
     73             public List<UnitItem> AddUnits
     74             {
     75                 get; set;
     76             }
     77 
     78             public Action<ICoroutineUnit,Exception> ErrorHandle { get; set; }
     79 
     80 
     81             private bool _running = false;
     82             private bool _continue = true;
     83 
     84             /// <summary>
     85             /// 仅当外部调用方调用时才启动
     86             /// 同时保证只有一个线程启动
     87             /// </summary>
     88             public void Run()
     89             {
     90                 lock (this)
     91                 {
     92                     if (_running)
     93                     {
     94                         _continue = true;
     95                     }
     96                     else
     97                     {
     98                         _continue = false;
     99                     }
    100 
    101                 }
    102 
    103                 if (!_running)
    104                 {
    105                     lock (this)
    106                     {
    107                         _running = true;
    108                     }
    109 
    110                     Task.Run(() =>
    111                         {
    112 
    113 
    114                                 while (true)
    115                                 {
    116                                     lock (this)
    117                                     {
    118                                         _continue = false;
    119                                     }
    120 
    121                                     while (true)
    122                                     {
    123                                         lock (AddUnits)
    124                                         {
    125                                             foreach (var addItem in AddUnits)
    126                                             {
    127                                                 Units.Add(addItem);
    128                                             }
    129                                             AddUnits.Clear();
    130                                         }
    131 
    132 
    133                                         if (Units.Count == 0)
    134                                         {
    135                                             break;
    136                                         }
    137 
    138                                         foreach (var item in Units)
    139                                         {
    140                                             if (item.UnitResult == null)
    141                                             {
    142                                                 var result = item.Unit.Do();
    143 
    144                                                 try
    145                                                 {
    146                                                     result.MoveNext();
    147                                                 }
    148                                                 catch (Exception ex)
    149                                                 {
    150                                                    
    151                                                     ErrorHandle(item.Unit, ex);
    152 
    153                                                     Units.Remove(item);
    154 
    155                                                     break;
    156                                                 }
    157 
    158                                                 item.UnitResult = result;
    159                                             }
    160                                             else
    161                                             {
    162                                                 if (item.UnitResult.Current.IsCanceled || item.UnitResult.Current.IsCompleted || item.UnitResult.Current.IsFaulted)
    163                                                 {
    164                                                     var nextResult = true;
    165                                                     try
    166                                                     {
    167                                                         nextResult = item.UnitResult.MoveNext();
    168                                                     }
    169                                                     catch (Exception ex)
    170                                                     {
    171                                                         ErrorHandle(item.Unit, ex);
    172 
    173                                                         Units.Remove(item);
    174 
    175                                                         break;
    176                                                     }
    177                                                     if (!nextResult)
    178                                                     {
    179 
    180                                                         Units.Remove(item);
    181 
    182                                                         break;
    183                                                     }
    184                                                 }
    185                                             }
    186                                         }
    187                                     }
    188 
    189 
    190                                     lock (this)
    191                                     {
    192                                         if (!_continue)
    193                                         {
    194                                             _running = false;
    195                                             break;
    196                                         }
    197                                     }
    198                                 }
    199 
    200 
    201 
    202                         });
    203                     
    204                 }
    205 
    206 
    207             }
    208 
    209 
    210 
    211 
    212         }
    213     }

    主程序调用

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             //错误处理
     6             Action<ICoroutineUnit, Exception> errorHandle = (unit, ex) =>
     7                 {
     8                     var response = ((HttpAction)unit).Response;
     9                     response.ContentType = "text/html";
    10                     string str = "访问出错,错误原因:" + ex.ToString();
    11                     var bytes = UTF8Encoding.UTF8.GetBytes(str);
    12                     response.OutputStream.Write(bytes, 0, bytes.Length);
    13                     response.OutputStream.Close();
    14                 };
    15             //容器初始化
    16              ICoroutineContainer coroutineContainerMultipleAuto = new CoroutineContainerMultipleAuto(2, errorHandle);
    17              coroutineContainerMultipleAuto.Run();
    18 
    19             //监听
    20              HttpListener listener = new HttpListener();
    21 
    22              listener.Start();
    23              listener.Prefixes.Add("http://localhost:8000/");
    24 
    25             while (true)
    26             {
    27                 var httpContext = listener.GetContext();
    28                 //创建Http请求的协程单元
    29                 HttpAction action = new HttpAction(httpContext.Request, httpContext.Response);
    30                 //注册分发协程单元
    31                 coroutineContainerMultipleAuto.Register(action);
    32             }
    33              
    34 
    35         }
    36 
    37 
    38     }

    程序执行后,

    打开浏览器访问,获得结果

    至此,基于自动多线程的协程简单框架完成

  • 相关阅读:
    Nexus 3048的NX-OS升级方法
    ASA防火墙忘记密码之后的恢复步骤
    关闭AnyConnect登录安全警告窗口
    使用vASA842配置ASDM645
    SSL 证书格式普及,PEM、CER、JKS、PKCS12
    Python基础练习
    理解管理信息系统
    各大搜索引擎蜘蛛的UserAgent
    iOS应用程序内购/内付费
    iOS开发解决:iOS8.1中UIBarButtonItem的setTitleTextAttributes对Disabled颜色设置无效问题
  • 原文地址:https://www.cnblogs.com/rhwleo/p/6853830.html
Copyright © 2020-2023  润新知