System.Threading.Channels限流功能未按预期工作,请求协助排查
问题分析与解决方案
你的问题核心在于没有等待WriteAsync的异步操作完成,同时错误地提前关闭了通道,导致第二个值丢失。
具体原因:
WriteAsync是异步方法,返回ValueTask,代表写入操作的完成状态。当有界通道已满时,WriteAsync不会立即完成,而是挂起等待通道有空位。但你直接调用WriteAsync却不等待它完成,程序会继续执行后续代码。- 在第二个
WriteAsync还在等待写入时,你调用了writer.Complete(),直接关闭了通道的写入端。此时未完成的写入任务会被取消,第二个值13永远不会被写入通道,自然也不会被消费。 - 控制台输出里的"Writing second value..."只是执行到了打印语句,不代表写入操作已经完成。
修正后的代码:
把Produce改成异步方法,等待每个WriteAsync完成后再继续,确保所有值都成功写入后再关闭通道:
public class Example { private readonly Channel<int> queue = Channel.CreateBounded<int>(1); public async Task Produce() { ChannelWriter<int> writer = queue.Writer; Console.WriteLine("Writing first value..."); await writer.WriteAsync(7); // 等待第一个值写入完成 Console.WriteLine("First value written, waiting for channel to free..."); Console.WriteLine("Writing second value..."); await writer.WriteAsync(13); // 等待通道有空位后写入第二个值 Console.WriteLine("Finishing writing..."); writer.Complete(); } public async Task Consume() { await Task.Delay(5000); ChannelReader<int> reader = queue.Reader; await foreach (int value in reader.ReadAllAsync()) Console.WriteLine($"Consumed: {value}"); Console.WriteLine("Done..."); } }
运行修正后的代码,Produce方法会在第一个值写入后,等待消费者取出值(通道有空位),才会继续写入第二个值。此时输出会变成:
Writing first value... First value written, waiting for channel to free... Writing second value... Consumed: 7 Consumed: 13 Finishing writing... Done...
额外注意点:
- 永远不要忽略异步方法的返回任务,尤其是像
WriteAsync这种依赖通道状态的操作,必须通过await确保操作完成。 - 调用
Complete()前,要确保所有写入操作都已完成,否则会导致未完成的写入失败。
内容的提问来源于stack exchange,提问作者walruz
相关产品推荐
相关产品推荐

