How to correctly dispose System.Threading.Channels

Viewed 351

The subject says it all. Specifically, say I created Channels this way.

Channel<byte[]> Stream { get; set; }

void Create() 
{
  Stream = System.Threading.Channels.Channel.CreateUnbounded<byte[]>();
}

Question

Is it ok to dispose it in the following order?

public virtual void Dispose()
{
  if (Stream.Writer.TryComplete()) // Dispose writer
  {
    Stream.Reader.Completion.ContinueWith(o => // Dispose reader
    {
      // Dispose the rest, e.g. some streaming server 

    }).Unwrap();
  }
}

P.S. In general, it works, but I'd like to make sure that if this code will be executed multiple times it won't cause memory leaks or unexpected runtime exceptions.

1 Answers

I think your dispose method is correct because TryComplete returns true only once and it is thread safe.

But there is a problem, you expose the channel to subscribers, so they are able to explicitly call TryComplete/Complete to finish the writer. It's better to conceal it and just expose a write method.

public class StreamServer : IDisposable
{
    protected virtual Channel<byte[]> Stream { get; set; }
    public ValueTask WriteAsync(byte[] item) => Stream.Writer.WriteAsync(item);
}
Related