如何在C#中使用Channels进行异步排队

本篇文章是对如何在asp.net core 的web api中使用Channels的简单介绍.

如何在C#中使用Channels进行异步排队

引子

设想一下我们有这样一个典型的生产者/消费者问题,我在controller 上收到一个请求并希望通过后台服务执行任务。
相信你的第一个想法是使用一些外部的消息队列来实现,如 RabbitMQ 或Kafka,这对于这样的一个简单任务来说这些组件都有点重了。所以我决定在不使用任何外部消息队列的情况下实现它。

所以我的第一次尝试是使用ConcurrentQueue和一些锁,但它变得很复杂。所以我尝试搜索一些更简单的方式,直到我找到了“Channels”。

Channels是什么

一个 Channel 是一个 . NET 数据结构或集合,我们可以在其中存储来自生产者的数据,同时消费者可以检索它,而无需从我们这边进行任何额外的同步。

如何在C#中使用Channels进行异步排队

生产者/消费者描述了生产者发布消息的行为,并且有一个或多个消费者可以对该消息进行处理,但每条消息只能读取一次。它不会对每个订阅者进行重复消费。换句话说就是,消费者之间是竞争消费。

例子

当我搜索示例时,我发现了很多控制台应用程序示例,但没有针对 Web API的,因此我决定尝试以 ASP.Net Core Web API 项目为例来进行演示

所以让我们开始吧。

在 Visual Studio 中创建一个 Web API 项目,或者您可以使用下面的 cmd命令进行创建

dotnet new webapi -o LearningChannels

现在为了简单起见,我使用两个后台任务,一个用于生产者,一个用于消费者。

WriterService

如何在C#中使用Channels进行异步排队

ReaderService

如何在C#中使用Channels进行异步排队

而对于ASP.NET Core Web API,最重要的部分是定义通道和依赖注入。

如何在C#中使用Channels进行异步排队

我们已经完成了更改。

让我们测试一下。运行应用程序

如何在C#中使用Channels进行异步排队

正如我们在输出窗口中看到的那样,一旦数据写入Channels,消费者就会读取它。

现在,如果您在我的示例中注意到我使用了无界Channels。

那是什么,还有什么其他选择。让我们看看他们。

有界Channels和无界Channels

CreateUnbounded方法创建一个对可以存储的项目数量没有限制的channel。当然在某些时候它可能会达到内存的限制,这时候你会得到内存不足的异常。

另一方面,CreateBounded方法可以创建一个具有在创建期间提供的显式数量限制的通道。

有界Channels有一些用于指示不同行为的选项,BoundedChannelFullMode

public enum BoundedChannelFullMode
{
    Wait,
    DropNewest,
    DropOldest,
    DropWrite
}

默认为Wait,等待队列中有空间时写入。因此TryWrite将为此类channel返回 false

DropOldest将删除“最旧”的数据。

DropNewest将删除最新的数据。

DropWrite删除当前正在写入的数据。

因此,您可以根据你的场景选择适合的选项。

总结

在本教程中,我们已经了解了通道如何在应用程序中处理异步任务时发挥作用。

希望你喜欢阅读它。

快乐编码并继续学习..!

参考阅读:

https://medium.com/@niteshsinghal85/using-channels-for-asynchronous-queuing-in-c-ed96c51d4576