怪奇物语

怪奇物语

首页 新随笔 联系 管理

消息队列,Channel,无界队列,有界队列

  1. 因为队列的最大长度是 3,所以从 B 到 E 的消息被掉丢
  2. A 为什么没有丢掉,是因为刚写入的 A 消息被队列接收了,然后又写入了 B,C,D,E,F,G,H,然后 B 到 E 的消息被丢掉
D:\Code\ServiceModel.Grpc-master\Examples\SimpleChat\ChannelMsg>dotnet run
[写入] A: 1,写入成功: True
[写入] B: 2,写入成功: True
[写入] C: 3,写入成功: True
[写入] D: 4,写入成功: True
[写入] E: 5,写入成功: True
[写入] F: 6,写入成功: True
[写入] G: 7,写入成功: True
[写入] H: 8,写入成功: True
[读取] A: 1
[读取] F: 6
[读取] G: 7
[读取] H: 8

ChannelMsg\ChatConnection.cs


using System.Runtime.CompilerServices;
using System.Threading.Channels;

public class ChatConnection : IObserver<ChatMessage>
{
    private const int MaxStuckMessages = 3;
    private readonly Channel<ChatMessage> _channel;

    public ChatConnection()
    {

        // - 构造函数,初始化 `_channel` 为有界队列,最多缓存 10 条消息。
        //     - `AllowSynchronousContinuations = false`:不允许同步执行回调,避免死锁。
        //     - `FullMode = BoundedChannelFullMode.DropOldest`:队列满时丢弃最早的消息。
        //     - `SingleReader = true`:只有一个消费者读取消息。
        //     - `SingleWriter = true`:只有一个生产者写入消息。
        _channel = Channel.CreateBounded<ChatMessage>(
            new BoundedChannelOptions(MaxStuckMessages)
            {
                AllowSynchronousContinuations = false,
                FullMode = BoundedChannelFullMode.DropOldest,
                SingleReader = true,
                SingleWriter = true
            }
        );
    }

    public void OnCompleted() => _channel.Writer.TryComplete();

    public void OnError(Exception error) => _channel.Writer.TryComplete(error);

    public void OnNext(ChatMessage value)
    {
        bool written = _channel.Writer.TryWrite(value);
        Console.WriteLine($"[写入] {value.Author}: {value.Content},写入成功: {written}");
    }

    public async IAsyncEnumerable<ChatMessage> AsEnumerable([EnumeratorCancellation] CancellationToken cancellationToken)
    {
        while (await _channel.Reader.WaitToReadAsync(cancellationToken))
        {
            while (_channel.Reader.TryRead(out var message))
            {
                // Console.WriteLine($"[读取] {message.Author}: {message.Content}");
                yield return message;
            }
        }
    }
}

ChannelMsg\ChatMessage.cs


public class ChatMessage
{
    public required string Author { get; set; }
    public required string Content { get; set; }
}

ChannelMsg\Program.cs


var conn = new ChatConnection();
var cts = new CancellationTokenSource();

// 消费者
var consumer = Task.Run(async () =>
{
    await foreach (var msg in conn.AsEnumerable(cts.Token))
    {
        await Task.Delay(1000); // 模拟处理时间
        Console.WriteLine($"[读取] {msg.Author}: {msg.Content}");
    }
});

// 生产者
conn.OnNext(new ChatMessage { Author = "A", Content = "1" });
conn.OnNext(new ChatMessage { Author = "B", Content = "2" });
conn.OnNext(new ChatMessage { Author = "C", Content = "3" });
conn.OnNext(new ChatMessage { Author = "D", Content = "4" });
conn.OnNext(new ChatMessage { Author = "E", Content = "5" });
conn.OnNext(new ChatMessage { Author = "F", Content = "6" });
conn.OnNext(new ChatMessage { Author = "G", Content = "7" });
conn.OnNext(new ChatMessage { Author = "H", Content = "8" });

await Task.Delay(500);
conn.OnCompleted();
await consumer;

posted on 2025-06-15 08:00  超级无敌美少男战士  阅读(18)  评论(0)    收藏  举报