System.Threading.Channels命名空间包含可用于实现生产者-消费者方案的类型,该类型通过允许生产者和消费者同时执行其任务来加快处理速度。 此名称空间包含一组同步类型,可用于生产者和使用者之间的异步数据交换。
本文讨论了如何使用.NET Core中的System.Threading.Channels库。
[ 同样在InfoWorld上:敏捷软件开发经理的5个职责 ]
数据流块与通道
System.Threading.Tasks.Dataflow库封装了存储和处理,并且主要集中在流水线上。 相比之下,System.Threading.Tasks.Channels库主要专注于存储。 通道比Dataflow块快得多,但它们特定于生产者-消费者方案。 这意味着它们不支持您使用Dataflow块获得的某些控制流功能。
为什么要使用System.Threading.Channels?
您可以利用渠道在发布和订阅方案中使生产者与消费者脱钩。 生产者和消费者不仅可以通过并行工作来提高性能,而且如果其中一项任务开始超过其他任务,则可以创建更多的生产者或消费者。 换句话说,生产者-消费者模式有助于提高应用程序的吞吐量(一种度量,它表示单位时间内完成的工作量)。
若要使用本文中说明的代码示例,您应该在系统中安装Visual Studio 2019。 如果您还没有副本,则可以在此处下载Visual Studio 2019 。
在Visual Studio中创建一个.NET Core Console App项目
首先,让我们在Visual Studio中创建一个.NET Core项目。 假设系统中已安装Visual Studio 2019,请按照以下概述的步骤创建新的.NET Core控制台应用程序。
- 启动Visual Studio IDE。
- 点击“创建新项目”。
- 在“创建新项目”窗口中,从显示的模板列表中选择“控制台应用程序(.NET Core)”。
- 点击下一步
- 在接下来显示的“配置新项目”窗口中,指定新项目的名称和位置。
- 单击创建。
这将在Visual Studio 2019中创建一个新的.NET Core控制台应用程序项目。在本文的后续部分中,我们将使用该项目来说明System.Threading.Channels的用法。
安装System.Threading.Channels NuGet软件包
既然我们已经在Visual Studio中创建了一个.NET Core控制台应用程序,接下来您应该做的是安装必要的NuGet程序包。 您需要安装的软件包是System.Threading.Channels。 您可以从Visual Studio 2019 IDE中的NuGet程序包管理器安装此程序包。 或者,您可以输入以下命令以通过.NET CLI安装此软件包。
dotnet add package System.Threading.Channels
在.NET Core中创建频道
本质上,您可以拥有两种不同类型的渠道。 其中包括有限容量的有界通道和无限容量的无界通道。 您可以使用Channel静态类创建任一类型的通道,该类可作为System.Threading.Channels命名空间的一部分使用。
Channel类提供了以下两个工厂方法,可用于创建两种类型的通道。
- CreateBounded <T>用于创建容纳有限数量消息的通道。
- CreateUnbounded <T>用于创建容量不受限制的通道,即,(理论上)拥有无限数量的消息的通道。
以下代码段说明了如何创建无边界通道。 请注意,此通道只能容纳字符串对象。
var channel = Channel.CreateUnbounded<string>();
有界通道选项包括FullMode属性,该属性用于表示通道已满时在写操作期间通道的行为。 有界通道可以利用以下任何FullMode行为:
- 等待
- DropWrite
- 最新
- 最旧的
以下代码段说明了如何创建有界通道并设置FullMode属性。
Channel.CreateBounded<string>(new BoundedChannelOptions(1000)
{
FullMode = BoundedChannelFullMode.Wait
});
将数据写入.NET Core中的通道
要将数据写入通道,可以使用WriteAsync方法,如下面给出的代码片段所示。
await channel.Writer.WriteAsync("Hello World!");
从.NET Core中的通道读取数据
要从通道读取数据,可以利用ReadAsync方法,如下面的代码片段所示。
while (await reader.WaitToReadAsync())
{
if (reader.TryRead(out var message))
{
Console.WriteLine(message);
}
}
System.Threading.Channels示例
这是完整的代码清单,演示了如何在通道中写入数据以及从通道中读取数据。
class Program
{
static async Task Main(string[] args)
{
await SingleProducerSingleConsumer();
Console.ReadKey();
}
public static async Task SingleProducerSingleConsumer()
{
var channel = Channel.CreateUnbounded<int>();
var reader = channel.Reader;
for(int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i + 1);
}
while (await reader.WaitToReadAsync())
{
if (reader.TryRead(out var number))
{
Console.WriteLine(number);
}
}
}
}
执行后,上述程序将在控制台窗口中顺序显示数字1到10。
有多种实现生产者-消费者模式的方法,例如使用BlockingCollection或TPL Dataflow。 但是,频道比这两个频道都快得多,效率也更高。 我将在以后的文章中进一步详细讨论渠道。 在此之前,您可以从Microsoft的在线文档中了解有关System.Threading.Channels命名空间的更多信息。