Channels
Building on the Duplex Pipes infrastructure, NexNet provides typed channel interfaces for streaming structured data between server and client. Channels handle serialization and deserialization automatically.
Channel Types
NexNet offers two channel interfaces, each optimized for different data types:
| Interface | Best For | Thread Safety |
|---|---|---|
INexusDuplexChannel<T> |
Any type serializable by MemoryPack | Writing is thread safe; reading should be single-threaded |
INexusDuplexUnmanagedChannel<T> |
Unmanaged types (primitives, simple structs) | Writing is thread safe; reading should be single-threaded |
Always prefer INexusDuplexUnmanagedChannel<T> when working with unmanaged types — it is fine-tuned for performance of simple types.
Defining a Channel Method
Add a channel parameter to a nexus interface method:
public interface IServerNexus
{
ValueTask StreamData(INexusChannel<ComplexMessage> channel);
ValueTask StreamIntegers(INexusChannel<int> channel);
}
Like duplex pipes, channel methods must return ValueTask and cannot use CancellationToken (channels have built-in cancellation/completion notifications).
Creating Channels
Channels are acquired through the client or session context:
// On the client
var channel = client.CreateChannel<MyMessage>();
var unmanagedChannel = client.CreateUnmanagedChannel<int>();
// On the server (inside a nexus method)
var channel = Context.CreateChannel<MyMessage>();
var unmanagedChannel = Context.CreateUnmanagedChannel<int>();
If a channel instance is created, it should be disposed to release held resources.
Reading with IAsyncEnumerable
The preferred method of reading channels is using IAsyncEnumerable on the INexusChannelReader. This provides efficient buffering and simplifies handling of channel closure, whether graceful or not:
// Given an INexusDuplexPipe from a method argument
var writer = await duplexPipe.GetUnmanagedChannelWriter<int>();
await foreach (var msg in await duplexPipe.GetChannelReader<ComplexMessage>())
{
// Process each message
}
Extension Methods
Several extension methods simplify reading and writing entire collections:
WriteAndComplete
Writes a collection to a channel and signals completion:
// Write to INexusDuplexChannel<T> or INexusChannelWriter<T>
await channel.WriteAndComplete(items, batchSize: 100);
The optional batchSize parameter controls how many items are sent per batch for optimized transmission.
ReadUntilComplete
Reads all items from a channel until the sender signals completion:
// Read from INexusDuplexChannel<T> or INexusChannelReader<T>
var items = await channel.ReadUntilComplete<MyMessage>(initialSize: 1000);
The optional initialSize parameter pre-allocates collection capacity to reduce resizing during reads.
See Also
- Duplex Pipes — Low-level byte streaming
- Hub Invocations — Method compatibility table for channel arguments