A rather tricky one here but the concept I'm trying to fathom is fairly simple.
I have a public static concurrent dictionary, accessible from other classes and threads:
public static readonly ConcurrentDictionary<int, object> tcpServerChannelDictionary = new ConcurrentDictionary<int, object>();
I have one particular background thread where I initially create a new C# Channel and store the instance inside the dictionary. Within this same thread (in the same method) I then start to wait for messages asynchronously. Have removed some unnecessary code bloat from the method:
var myChannel = Channel.CreateUnbounded<string>();
tcpServerChannelDictionary.TryAdd(int, myChannel);
await foreach (var data in myChannel.Reader.ReadAllAsync())
{
// Do something with message
}
First stumbling block was I couldn't define the static dictionary with the "object" as a channel i.e. ConcurrentDictionary<int, Channel>... becuase I'd get a warning sign that "Channel: Static Types cannot be used as type arguments" so this is why I declared an object type instead.
This appeared to work without VS code warnings until I then try to access the dictionary object from another class (and what will be another thread):
if (TcpServer.tcpServerChannelDictionary.TryGetValue(int, out Channel myChannel))
{
await myChannel.Writer.WriteAsync(data);
}
I somehow need to either cast the object to the channel I'm trying to acess so i can write a message to it, or some other solution that prevents the warnings. I'm new to channels but saw immediately how powerful using them will be.
The Channel
class is a helper static class with factory methods on it. All of those methods return a Channel<T>
. In your case you are creating Channel<string>
objects, and that's a type that a Dictionary can be constructed from.
public static readonly ConcurrentDictionary<int, Channel<string>> tcpServerChannelDictionary = new();
//...
if (TcpServer.tcpServerChannelDictionary.TryGetValue(int, out var /*Channel<string>*/ myChannel))
{
await myChannel.Writer.WriteAsync(data);
}
Now if for whatever reason you still needed to use the object
type for the values of your dictionary (maybe you have different generic parameters for Channel<T>
and you want them all in the same collection) your out
variable still needs to be object
and then you need to cast it:
if (TcpServer.tcpServerChannelDictionary.TryGetValue(int, out var /*object*/ oChannel) && oChannel is Channel<string> myChannel)
{
await myChannel.Writer.WriteAsync(data);
}