利用迭代器在.NET中实现“超轻量级线程”

原创|其它|编辑:郝浩|2009-10-09 10:39:03.000|阅读 377 次

概述:经常在python,lua之类的脚本语言看到 超轻量级线程的概念,动辄上百万的线程,硕大的线程数量非常的养眼,今天突发奇想,在c#下也来弄个超轻量线程的实现,虽然很简陋,但是希望能和大家一起来讨论讨论。

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

经常在python,lua之类的脚本语言看到 超轻量级线程的概念,动辄上百万的线程,硕大的线程数量非常的养眼,今天突发奇想,在c#下也来弄个超轻量线程的实现,虽然很简陋,但是希望能和大家一起来讨论讨论。

且不说超轻量级的线程有用无用。其实现原理基本上都是在单线程中来模拟线程的切换,由于没有线程切换的开销,所以看着比系统线程要快。在python中一般通过yield关键字来实现。翻遍msdn发现c#也有yield return的关键字。yield return 用于实现迭代器。什么是迭代器呢,这是.NET2.0所带来的特征,如果不清楚请参见

http://msdn.microsoft.com/zh-cn/library/dscyy5s0(VS.80).aspx

其大意是:

yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。

这段对我们将要实现的功能尤其重要,其实一言盖之,yield可以把一个方法分成几段来执行。但是在C#里有限制,在调用yield的方法的返回值必须是IEnumerable,其实说白了,其实是编译器自动把这段方法转换成了一个迭代器的对象,这样一段调用其实也就是在编译的时候就已经被分段了。根据msdn的原文描述就是:

迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使您能够在结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。您只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。

要通过yield来模拟线程,我们必须有线程体,由于yield的限制,我们就通过迭代器的方法来作为线程体,然后每个线程一个对象,每个对象里包含一个迭代器对象,然后在一个大循环里来调用。代码如下:


  1using System;
  2using System.Collections;
  3using System.Collections.Generic;
  4
  5public class MyClass
  6{
  7    public static void RunSnippet()
  8    {
  9        ThreadLite tl=new ThreadLite();
 10        tl.AddActor(T1);
 11        tl.AddActor(T1);
 12        tl.Run();
 13        
 14    }

 15    public static IEnumerable T1(int id){
 16        for(int i=0;i<10;i++){
 17            Console.WriteLine("Thread "+id+" print "+i);
 18            yield return id;
 19        }

 20    }

 21    public static IEnumerable T2(int id){
 22        for(int i=0;i<8;i++){
 23            Console.WriteLine("Thread "+id+" print "+i);
 24            yield return id;
 25        }

 26    }

 27    
 28    
 29    Helper methods
 65}

 66
 67class ThreadLite{
 68    int currentid = 1;
 69    public delegate IEnumerable ActorHandler(int id);
 70    private List<IEnumerator> ActionList;
 71    public ThreadLite(){
 72        ActionList=new List<IEnumerator>();
 73    }

 74    public void AddActor(ActorHandler actor){
 75        Actor act=new Actor(actor);
 76        act.ID=this.currentid;
 77        ActionList.Add(act.GetEnumerator());
 78        this.currentid++;
 79    }

 80    
 81    public void Run(){
 82        int fc = 0;
 83        while(true){
 84            foreach(IEnumerator ie in ActionList){
 85                if(!ie.MoveNext()){
 86                    fc++;
 87                }

 88            }

 89            if(fc==ActionList.Count){
 90                break;
 91            }

 92        }

 93        
 94    }

 95    
 96    class Actor{
 97        public int ID{
 98            get;
 99            set;
100        }

101
102        ThreadLite.ActorHandler hdl;
103        public Actor(ThreadLite.ActorHandler handler){
104            hdl=handler;
105        }

106        public IEnumerator GetEnumerator(){
107            IEnumerable ieb = hdl(ID);
108            return ieb.GetEnumerator();
109        }

110    }

111    
112}

执行结果如下:


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP