.NET中使用Channel<T>

在面对 生产者-消费者 的场景下, netcore 提供了一个新的命名空间 System.Threading.Channels 来帮助我们更高效的处理此类问题,有了这个 Channels 存在, 生产者 和 消费者 可以各自处理自己的任务而不相互干扰,有利于两方的并发处理,这篇文章我们就来讨论下如何使用 System.Threading.Channels。

为什么要使用 Channels

可以利用 Channels 来实现 生产者和消费者 之间的解耦,大体上有两个好处:

  • 生产者 和 消费者 是相互独立的,两者可以并行执行。

  • 如果生产者不给力,可以创建多个的生产者,如果消费者不给力,可以创建更多的消费者。

总的来说,在 生产者-消费者 模式下可以帮助我们提高应用程序的吞吐率。

创建 channel

本质上来说,你可以创建两种类型的 channel,一种是有限容量的 bound channel,一种是无限容量的 unbound channel,接下来的问题是,如何创建呢?Channels 提供了两种 工厂方法 用于创建,如下代码所示:

  CreateBounded<T> 创建的 channel 是一个有消息上限的通道。

  CreateUnbounded<T> 创建的 channel 是一个无消息上限的通道。

l例如

 public class IntervalBackgroundService : BackgroundService
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="stoppingToken"></param>
        /// <returns></returns>
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _ = SendQueue(stoppingToken);
            return Task.CompletedTask;
        }
        async Task SendQueue(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested && await ThreadChannels.IsWait())
            {
                ReservationParam pos = ThreadChannels.Take();
                if (pos == null)
                {
                    continue;
                }
                await new MessageFacade().SendReservationMsg(pos);
            };
        }
    }
/// <summary>
    /// 通道是线程安全的
    /// </summary>
    public class ThreadChannels
    {
        public static Channel<ReservationParam> threadChannels { get; set; } = Channel.CreateUnbounded<ReservationParam>();

        public static bool Add(ReservationParam msg)
        {
            if (threadChannels == null)
            {
                threadChannels = Channel.CreateUnbounded<ReservationParam>();
            }
            return threadChannels.Writer.TryWrite(msg);
        }
        public static ReservationParam Take()
        {
            if (threadChannels == null)
            {
                threadChannels = Channel.CreateUnbounded<ReservationParam>();
            }
            threadChannels.Reader.TryRead(out ReservationParam pos);
            return pos;
        }
        public async static Task<bool> IsWait()
        {
            if (threadChannels == null)
            {
                threadChannels = Channel.CreateUnbounded<ReservationParam>();
            }
            return await threadChannels.Reader.WaitToReadAsync();
        }
    }

 

 

 

 

 

posted @ 2021-06-21 10:23  netlock  阅读(508)  评论(0编辑  收藏  举报