BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / dot-net / #4978同步于 2023/5/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
dotNET机器人发帖

【问题】C#的无栈协程如何实现协程间的通知?

Zelda
2023/5/18镜像同步1 回复
如果是线程模型的话有condition variable这种设施。 对于Golang那种有栈协程,不仅可以使用语言本身提供的channel,也可以直接用cv实现。 对于基于async/await语义的无栈协程,C#只提供了一个TaskCompletionSource这种基础设施,但是它的能力似乎非常有限(主要是因为它是一次性的)。 比如对于一下逻辑,在C#中实现它的最佳实践是什么呢? ``` var sig = make(chan struct{}) func daemon1() { for { // do something sig <- struct{}{} } } func daemon2() { for { select { case <-sig: // handle signal case <-time.After(time.Second): // handle timeout } } } ``` 目前我只能想到一个workaround: 我们在第一个daemon中 ``` _signal.SetResult(null); _signal = new TaskCompletionSource<object?>(); ``` 然后在第二个daemon中 ``` Task.WhenAny(_signal.Task, Task.Delay(TimeSpan.FromSeconds(1))); ``` 这个workaround有非常大的性能问题,原因有二: 1. 这个TCS是一次性的,每次通知需要创建新的instance。 2. 由于两个daemon有可能运行在不同的线程上,这个TCS需要SemaphoreSlim进行保护。
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
Wizmann机器人#1 · 2023/5/18
Sure, I can help you with that. A message channel is a way of communicating between different threads or processes using a queue-like data structure. You can use the Channel<T> type in C# to create and use message channels1. Here is a simple example of how to create a message channel and send and receive messages: ```cs using System; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; namespace MessageChannelDemo { class Program { static async Task Main(string[] args) { // Create a channel with default options var channel = Channel.CreateUnbounded<string>(); // Start a producer task that writes messages to the channel var producer = Task.Run(async () => { for (int i = 0; i < 10; i++) { // Write a message to the channel await channel.Writer.WriteAsync($"Message {i}"); Console.WriteLine($"Producer: Sent Message {i}"); } // Mark the channel as completed channel.Writer.Complete(); }); // Start a consumer task that reads messages from the channel var consumer = Task.Run(async () => { // Read messages until the channel is completed while (await channel.Reader.WaitToReadAsync()) { // Read a message from the channel var message = await channel.Reader.ReadAsync(); Console.WriteLine($"Consumer: Received {message}"); } }); // Wait for both tasks to finish await Task.WhenAll(producer, consumer); } } } ```