C# 关于PipeLine管道的用法

pipeline类似于工厂加工,开始给一堆的零件,通过各个管道之后,从最后出口出来之后就是一件成品。管道链类似的责任。的主要区别是,链,每个“链接”传递到下一个,直到人知道如何处理它,那么这个过程停止。在管道,传递给每一个链的链接和潜在的修改通过。这就是“管道和过滤器”发挥作用,因为一个链接可以过滤管可能会增加其他链接。

代码如下:

中间过程的接口:

一个上下文的结构:知道自己的上一个和下一个管道

public class HandlerContext
    {
        private IEventHandler _handler;

protected HandlerContext()
            : this(null)
        {
        }

public HandlerContext(IEventHandler handler)
        {
            _handler = handler;
            Next =null;
            Prev = null;
        }

public virtual IEventHandler Handler
        {
            get { return _handler; }
        }

public static Task<object> Invoke(HandlerContext ctx, object data, TaskCompletionSource<Object> tcs = null)
        {
            var promise = tcs ?? new TaskCompletionSource<object>();
            if (ctx != null)
            {
                ctx.Handler.Process(ctx, data, promise);
            }
            return promise.Task;
        }

public Task<object> FireProcess(object data)
        {
            var next = this.Next;
            return Invoke(next, data);
        }

public Task<object> FireProcess(object data, TaskCompletionSource<Object> tcs)
        {
            var next = this.Next;
            return Invoke(next, data, tcs);
        }

internal HandlerContext Next;
        internal HandlerContext Prev;
    }

PipeLine类:作用是添加中间的管道

class AlarmPipeline
    {
        private readonly HandlerContext _head;
        private readonly HandlerContext _tail;

public AlarmPipeline()
        {
            _head = new Decoder();
            _tail = new Renderer();
            _head.Next = _tail;
            _tail.Prev = _head;
        }

public void AddLast(IEventHandler handler)
        {
            var newcontext = new HandlerContext(handler);
            var prev = _tail.Prev;
            prev.Next = newcontext;
            newcontext.Prev = prev;
            _tail.Prev = newcontext;
        }

public void AddFirst(IEventHandler handler)
        {
            var newcontext = new HandlerContext(handler);
            var next = _head.Next;
            _head.Next = newcontext;
            newcontext.Next = next;
            newcontext.Prev = _head;
        }

public bool AddAfter(IEventHandler prev, IEventHandler handler)
        {
            HandlerContext ctx = null;
            var cur = _head;
            while (cur != null)
            {
                if (cur.Handler == prev)
                {
                    ctx = cur;
                    break;
                }
                cur = cur.Next;
            }

if (ctx == null)
                return false;

var newcontext = new HandlerContext(handler);
            var next = ctx.Next;
            ctx.Next = newcontext;
            newcontext.Next = next;
            newcontext.Prev = ctx;
            next.Prev = newcontext;
            return true;
        }

public void Remove(IEventHandler handler)
        {
            if (handler == null)
                return;

var low = _head.Next;
            var high = _tail.Prev;
            do
            {
                if (low != null)
                {
                    if (low.Handler == handler)
                    {
                        _DoRemove(low);
                    }
                    low = low.Next;
                }

if (high != null)
                {
                    if (high.Handler == handler)
                    {
                        _DoRemove(high);
                    }
                    high = high.Prev;
                }
            } while (low != high);
        }

public void RemoveFirst()
        {
            if (_head.Next == null) return;
            this.Remove(_head.Next.Handler);
        }

public void RemoveLast()
        {
            if (_tail.Prev == null) return;
            this.Remove(_tail.Prev.Handler);
        }

private void _DoRemove(HandlerContext ctx)
        {
            var prev = ctx.Prev;
            var next = ctx.Next;
            prev.Next = next;
            next.Prev = prev;
        }

public Task<object> Process(object data)
        {
            return HandlerContext.Invoke(_head, data);
        }

}

比如第一个管道:

class Decoder : HandlerContext, IEventHandler
    {
        public override IEventHandler Handler
        {
            get
            {
                return this;
            }
        }

public void Process(HandlerContext context, object data, TaskCompletionSource<object> tcs)
        {
            string url = (string)data;
            
            var provider = new Provider(url);
            provider.Load();

context.FireProcess(alarmdata, tcs);
        }
    }

时间: 2024-10-06 00:13:10

C# 关于PipeLine管道的用法的相关文章

Go语言的管道Channel用法

本文实例讲述了Go语言的管道Channel用法.分享给大家供大家参考.具体分析如下: channel 是有类型的管道,可以用 channel 操作符 <- 对其发送或者接收值. ch <- v // 将 v 送入 channel ch. v := <-ch // 从 ch 接收,并且赋值给 v. ("箭头"就是数据流的方向.) 和 map 与 slice 一样,channel 使用前必须创建: ch := make(chan int) 默认情况下,在另一端准备好之前,

Python高级编程之生成器(Generator)与coroutine(二):coroutine与pipeline(管道)和Dataflow(数据流_

原创作品,转载请注明出处:点我 在前两篇文章中,我们介绍了什么是Generator和coroutine,在这一篇文章中,我们会介绍coroutine在模拟pipeline(管道 )和控制Dataflow(数据流)方面的运用. coroutine可以用来模拟pipeline行为.通过把多个coroutine串联在一起来实现pipe,在这个管道中,数据是通过send()函数在各个coroutine之间传递的: 但是这些在pipe中传递的数据哪里来的呢?这就需要一个数据源,或者说producer.这个

使用pipeline管道执行redis命令

pipeline管道可以减少后端与redis的连接次数,从而实现了优化. 原理如下: 使用方法: 未使用pipeline前: strict_redis = get_redis_connection('sms_codes') # type:StrictRedis strict_redis.setex('sms_%s' % mobile,constants.SMS_CODE_REDIS_EXPIRES, sms_codes) strict_redis.setex('send_flag_%s' % m

Linux &#160; 管道的用法

将第一个命令的标准输出连接到下个命令的标准输入上 (第一个命令输出的数据为下一个命令的标准输入) 用法:       命令 | 命令                    (用几个管道没有限制) 输出日志 用管道输出日志的行数 注意 管道是按从左到右的顺序执行 管道命令只处理 stdout 对于 stderr 不处理 如遇 stderr 忽略它 继续执行其它的

10.26的总结, 管道流用法, RandomAccessFile, DataStream 有待深入.

1 package test; 2 import java.io.*; 3 import java.nio.channels.FileChannel; 4 import java.util.*; 5 public class Test10_26 6 { 7 public static void main(String[] args) throws Exception 8 { 9 10 } 11 public static void method_delete() 12 { 13 File dir

Apache Beam实战指南 | 大数据管道(pipeline)设计及实践

Apache Beam实战指南 | 大数据管道(pipeline)设计及实践  mp.weixin.qq.com 策划 & 审校 | Natalie作者 | 张海涛编辑 | LindaAI 前线导读: 本文是 Apache Beam 实战指南系列文章第五篇内容,将对 Beam 框架中的 pipeline 管道进行剖析,并结合应用示例介绍如何设计和应用 Beam 管道.系列文章第一篇回顾 Apache Beam 实战指南 | 基础入门.第二篇回顾 Apache Beam 实战指南 | 玩转 Kaf

MongoDB基础教程系列--第七篇 MongoDB 聚合管道

在讲解聚合管道(Aggregation Pipeline)之前,我们先介绍一下 MongoDB 的聚合功能,聚合操作主要用于对数据的批量处理,往往将记录按条件分组以后,然后再进行一系列操作,例如,求最大值.最小值.平均值,求和等操作.聚合操作还能够对记录进行复杂的操作,主要用于数理统计和数据挖掘.在 MongoDB 中,聚合操作的输入是集合中的文档,输出可以是一个文档,也可以是多条文档. MongoDB 提供了非常强大的聚合操作,有三种方式: 聚合管道(Aggregation Pipeline)

Angular2 管道

1. 说明 管道用来转换模板显示的内容,应用程序中经常出现获取数据,转换数据,显示数据的逻辑.管道就是用来在转换数据阶段起作用的.主要存在两种类型的管道,pure pipe和impure pipe 2. Pure Pipe Pure Pipe,stateless,关注于纯粹对象的变更,检测到输入值发生了 纯变更 时才会执行 纯管道 . 纯变更 是指对原始类型值 (String .Number . Boolean . Symbol) 的更改, 或者对对象引用 (Date . Array . Fun

重定向、管道和用户管理练习题

一.重定向.管道的用法练习 1.将/etc/issue文件的内容转换为大写保存到/tmp/issue.out文件中 [[email protected] ~]# tr [a-z] [A-Z] < /etc/issue > /tmp/issue.out  [[email protected] ~]# cat /tmp/issue.out  \S KERNEL \R ON AN \M 或者 [[email protected] ~]# tr '[:lower:]' '[:upper:]' <