`
qiezi
  • 浏览: 497880 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用C#的Generator编写并发程序

阅读更多
前面说地Generator编写并发程序的优势,当然它本身没有这种能力,需要为它编写调度程序。

今天抽点时间写了个简单的,还是满好玩的,它可以调度多个“友好”的并发任务,包括:
1、用户自己编写的适时交出控制权的过程
2、网络IO

由于对C#不是很熟,所以写的可能比较难看,而且IO也只支持网络,有兴趣的可以研究改进一下,比如把它改成SMP版本,增加Actor模型,处理更多的IO模式等。

实现方式基本上是从IoLanguage里面抄过来的,我已经用它编写过Ruby/C++/D/C#版本,当然目前仅限于测试它的切换性能。

好消息是如果你实现得比较好,C#版本性能完全可以超过Erlang,Ruby的Fiber就比较差一些,C++/D里面使用Fiber/ucontext性能也不是很好,Generator性能是最好的。

由于时间短,只测试了ReadEvent,WriteEvent没有测试,这个也是有多种实现方式可以研究的。这里实现的调度器性能不是很好,可能是List用法性能太差,没有仔细测试。
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;


namespace ConsoleApplication1
{
    public enum EventType
    {
        ReadEvent = 1,
        WriteEvent = 2
    }

    public class Event
    {
        private Socket sock;
        private EventType eventType;
        private IEnumerator<int> task;

        public Event(Socket sock, EventType eventType)
        {
            this.sock = sock;
            this.eventType = eventType;
        }

        public Socket getSocket()
        {
            return sock;
        }

        public EventType getEventType()
        {
            return eventType;
        }

        public void setTask(IEnumerator<int> task)
        {
            this.task = task;
        }

        public IEnumerator<int> getTask()
        {
            return task;
        }

        public void onEvent()
        {
            Console.WriteLine("onEvent");
            Scheduler.scheduleNow(task);
        }
    }

    public class ReadEvent : Event
    {
        public ReadEvent(Socket sock)
            :base(sock, EventType.ReadEvent)
        {
            
        }
    }

    public class WriteEvent : Event
    {
        public WriteEvent(Socket sock)
            : base(sock, EventType.WriteEvent)
        {
        }
    }

    class EventManager
    {
        private IDictionary<Socket, Event> readEvents = new Dictionary<Socket, Event>();
        private IDictionary<Socket, Event> writeEvents = new Dictionary<Socket, Event>();

        private IEnumerator<int> myTask = null;

        public int registerHandler(Event ev)
        {
            Console.WriteLine("registerHandler");
            if ((ev.getEventType() & EventType.ReadEvent) > 0)
            {
                readEvents.Add(ev.getSocket(), ev);
            }
            else
            {
                writeEvents.Add(ev.getSocket(), ev);
            }

            if (myTask == null)
                myTask = runLoop();


            Scheduler.scheduleNow(myTask);

            return 0;
        }

        public IEnumerator<int> runLoop()
        {
            Console.WriteLine("enter run");
            do
            {
                Console.WriteLine("run loop");
                yield return 1;

                IList rlist = new List<Socket>(readEvents.Keys);
                IList wlist = new List<Socket>(writeEvents.Keys);

                int timeoutMS = 1000000;
                if (Scheduler.hasEvents()) timeoutMS = 0;
                //Console.WriteLine("begin select: " + rlist.Count + ", " + wlist.Count);
                Socket.Select(rlist, wlist, null, timeoutMS);
                //Console.WriteLine("end select: " + rlist.Count + ", " + wlist.Count);

                Socket sock = null;
                Event ev = null;

                if (rlist.Count > 0)
                {
                    sock = (Socket)rlist[0];
                    readEvents.TryGetValue(sock, out ev);
                    readEvents.Remove(sock);
                }
                else if (wlist.Count > 0)
                {
                    sock = (Socket)wlist[0];
                    writeEvents.TryGetValue(sock, out ev);
                    writeEvents.Remove(sock);
                }

                if (ev != null)
                    ev.onEvent();
            } while (readEvents.Count != 0 || writeEvents.Count != 0);

            myTask = null;
        }
    }

    public static class Scheduler
    {
        public delegate IEnumerable<int> T();

        [ThreadStatic]
        private static IList<IEnumerator<int>> tasks = new List<IEnumerator<int>>();

        [ThreadStatic]
        private static EventManager eventManager = new EventManager();

        [ThreadStatic]
        private static Event lastEvent;

        public static bool hasEvents()
        {
            return tasks.Count > 0;
        }

        public static void spawn(T del)
        {
            var task = del().GetEnumerator();
            schedule(task);
        }

        public static void schedule(IEnumerator<int> task)
        {
            tasks.Remove(task);
            if (lastEvent != null)
                lastEvent.setTask(task);
            else
                tasks.Add(task);
            lastEvent = null;
        }

        public static void scheduleNow(IEnumerator<int> task)
        {
            tasks.Remove(task);
            tasks.Insert(0, task);
        }

        public static void remove(IEnumerator<int> task)
        {
            Console.WriteLine("remove task");
            tasks.Remove(task);
        }

        public static void run()
        {
            while (tasks.Count > 0)
            {
                IEnumerator<int> task = tasks[0];
                tasks.RemoveAt(0);
                bool ret = task.MoveNext();

                if (ret)
                    schedule(task);
            }
        }

        public static int registerAndWaitEvent(Event ev)
        {
            lastEvent = ev;
            return eventManager.registerHandler(ev);
        }
    }

    // 测试程序:

    class Program
    {
        public static IEnumerable<int> test(string id)
        {
            for (int i = 0; i < 5; i++)
            {
                System.Console.WriteLine("id: " + id + ", " +i);
                yield return i;
            }
        }

        public static IEnumerable<int> clientLoop(Socket client)
        {
            while (true)
            {
                Console.WriteLine("client loop");
                yield return Scheduler.registerAndWaitEvent(new ReadEvent(client));
                byte[] buffer = new byte[1024];
                int ret = client.Receive(buffer);
                if (ret > 0)
                {
                    //Console.WriteLine(buffer);
                    client.Send(buffer);
                }
                else
                {
                    client.Close();
                    break;
                }
            }
        }

        public static IEnumerable<int> serverLoop()
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPHostEntry IPHost = Dns.GetHostEntry("localhost"); 
            sock.Bind(new IPEndPoint(IPHost.AddressList[0], 23456));
            sock.Listen(128);
            while(true) {
                Console.WriteLine("server loop");
                yield return Scheduler.registerAndWaitEvent(new ReadEvent(sock));
                Console.WriteLine("accept event");
                Socket client = sock.Accept();
                Scheduler.spawn(() => clientLoop(client));
            }
        }

        static void Main(string[] args)
        {
            Scheduler.spawn(() => test("a"));
            Scheduler.spawn(() => test("b"));
            Scheduler.spawn(() => serverLoop());
            Scheduler.run();
        }
    }
}
5
0
分享到:
评论
1 楼 vdgame 2008-07-07  
不懂C#,老兄能不能给个c++的代码?谢谢先!

相关推荐

    C#压力测试程序,测试完毕后能够自动生成测试报表

    此C#程序可能同时包含了这两方面的功能,通过改变并发用户数量或请求频率,观察系统性能变化。 7. **性能监控**: 为了准确评估性能,需要监控CPU使用率、内存占用、磁盘I/O等系统资源。`System.Diagnostics`命名...

    C#根据时间产生ID编号

    为了避免这个问题,可以考虑使用`ThreadLocal&lt;Random&gt;`或`RandomNumberGenerator`类来生成随机数。 2. **ID唯一性的保证**: 上述方法生成的ID在大多数情况下都能保证唯一性,但在极端高并发的情况下仍可能存在...

    c#低开销随机不重复数

    在C#编程中,生成随机而不重复的数是一项常见的需求,尤其在游戏开发、抽奖程序、数据模拟等场景中。为了实现这样的功能,我们需要在保证效率的同时,尽可能地减少系统资源的消耗。以下是对"c#低开销随机不重复数"这...

    框架设计(第2版):CLR Via C#

    通过阅读《框架设计(第2版):CLR Via C#》,开发者不仅可以掌握.NET开发的高级技巧,还能深入了解CLR的工作机制,从而编写出更高效、更稳定、更安全的.NET应用程序。这本书对于任何想要在.NET平台上提升技术水平的...

    A cross-platform asynchronous HTTP(S) proxy server in C#..zip

    在C#中,异步操作使用了`async/await`关键字,这允许程序在等待I/O操作(如网络通信)完成时,不会阻塞主线程,从而提高了程序的响应性和效率。异步HTTP(S)代理服务器在处理大量并发连接时尤其有用,因为它能有效地...

    Microsoft.Press.CLR.via.C#.4th.Edition.2012

    《Microsoft.Press.CLR.via.C#.4th.Edition.2012》是一本针对.NET Framework中的公共语言运行时(Common Language Runtime, CLR)及其与C#编程语言结合使用的深度指南。这本书由著名.NET专家 Jeffrey Richter 撰写,...

    Marble Diagram Generator

    大理石图(Marble ...熟练使用这个工具,可以提升开发效率,避免在编写复杂数据流逻辑时出现错误。通过不断实践和研究大理石图,开发者能够更好地驾驭Rx的威力,为现代应用程序设计出高效、响应式的数据处理方案。

    c_sharp_load_generator

    "c_sharp_load_generator"是一个用C#编写的负载生成器项目,它允许开发者根据特定需求自定义负载测试场景,以便更好地评估和优化应用程序的性能。 一、C#语言基础 C#(读作"C sharp")是微软公司推出的一种面向...

    LoadRunner11+BS压力测试 超级详细的电子教程 新手必看

    7. **C#和ASP.NET集成测试**:如何在LoadRunner中对C#编写的ASP.NET应用进行集成测试,确保服务器端代码的性能。 8. **SQL性能测试**:利用LoadRunner的数据库监控功能,评估SQL查询的性能,找出可能的性能问题。 ...

    web测试:LOADRUNNER教程

    LOADRUNNER支持C#语言编写自定义函数和扩展,开发者可以通过C#来实现更复杂的功能,如数据驱动测试、动态参数化等。C#代码可以集成到LR脚本中,增强了测试的灵活性和可扩展性。 【LOADRUNNER教程】 LOADRUNNER教程...

    摇奖机系统

    3. `async/await` 关键字:C#5.0引入了异步编程模型,使用`async`和`await`关键字可以编写出非阻塞的异步代码,提高UI线程的响应性。 三、线程同步与互斥 1. `Mutex`:用于控制对共享资源的访问,确保同一时间只有...

    你必须知道的.NET

    11. **单元测试和持续集成**:掌握单元测试的基本概念,使用NUnit或xUnit编写测试,理解TDD(Test-Driven Development)和BDD(Behavior-Driven Development)。了解CI/CD(持续集成/持续部署)工具如Jenkins、Azure...

    .net条码打印软件源码.rar.rar

    开发者需要设置纸张大小、打印质量、页边距等参数,并编写绘制条码的事件处理程序。 5. **用户界面**:源码可能包含了创建用户界面的代码,如WinForms或WPF控件,允许用户输入条码数据、选择条码类型、预览条码以及...

    利用zint生成条码二维码并添加水印和打印功能

    首先,`Zint`库是用C语言编写的,但通过提供源代码,开发者可以在多种编程环境中使用,包括C++、C#、Python等。在本例中,描述中提到的是在Visual Studio 2010环境下使用C#进行开发。`Zint`为C#提供了.NET接口,使得...

    LOADRUNNER.NET插件

    .NET插件使得LoadRunner能够支持基于C#、VB.NET或其他.NET语言编写的Web、Windows或服务应用程序的性能测试。 使用LoadRunner.NET插件进行性能测试的步骤通常包括以下几点: 1. **录制脚本**:首先,使用...

    web-bench

    Web-Bench是一款基于C#语言编写的Web性能测试工具,主要功能是模拟多个并发用户对Web服务器进行压力测试,以评估服务器在高负载情况下的稳定性和性能。在深入理解Web-Bench之前,我们先来了解一下Web性能测试的基本...

    测试工作

    C#,作为Microsoft公司推出的一种面向对象的编程语言,广泛应用于Windows平台上的各种应用程序开发,包括但不限于桌面应用、游戏开发、服务器端服务以及Web应用。在C#环境中进行测试工作,我们可以利用其丰富的库和...

    状态测试

    在C#中,可以使用枚举或类来实现状态机,然后编写状态测试来验证状态转换的正确性。 5. **测试驱动开发(TDD)**: - TDD提倡先写测试,再写实现代码。在状态测试中,TDD可以帮助设计出更好的状态转换逻辑,因为测试...

    Visual Studio.NET 术语表

    6. **Design-Time Tools(设计时工具)**:Visual Studio .NET中的工具,如设计器和代码编辑器,用于在编写代码前可视化应用程序界面和逻辑。 7. **IDE(Integrated Development Environment,集成开发环境)**:...

    Test:Deze repo是测试对象

    标签为"C#",这表示这个测试仓库主要使用C#编程语言。C#是一种面向对象的、类型安全的、现代的编程语言,广泛应用于开发Windows桌面应用、Web应用、游戏以及移动应用。它由微软公司开发,并且在.NET框架和.NET Core...

Global site tag (gtag.js) - Google Analytics