8000 Document exceptions/behavior of ChannelWriter writing after writer is completed. · Issue #9250 · dotnet/dotnet-api-docs · GitHub
[go: up one dir, main page]

Skip to content
Document exceptions/behavior of ChannelWriter writing after writer is completed. #9250
Open
@poizan42

Description

@poizan42

Issue description

The documentation for ChannelWriter<T>.(TryWrite|WaitToWriteAsync|WriteAsync) does not say what happens in case the writer has been completed. In fact WaitToWriteAsync throws the exception set in ChannelWriter.Complete(Exception) if specified while returing false if no exception was specified. In contrast WriteAsync always throws a System.Threading.Channels.ChannelClosedException, optionally with the supplied exception as its InnerException. Neither of these are documented as throwing any exceptions.

The following program generates the same output on .NET 6.0 and .NET Framework 4.8

Test program source
using System;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace ChannelTest;

public class Program
{
    private static string GetExceptionDescriptionWithInnerExceptions(Exception e)
    {
        if (e.InnerException != null)
            return $"{e.GetType().FullName}: {e.Message}  ---> {GetExceptionDescriptionWithInnerExceptions(e.InnerException)}";
        else
            return $"{e.GetType().FullName}: {e.Message}";
    }
    private static void PrintResultOrError(string op, Func<Task> f)
        => PrintResultOrError(op, async () => { await f(); return "Success"; });
    private static void PrintResultOrError<T>(string op, Func<T> f)
        => PrintResultOrError(op, () => Task.FromResult(f()));
    private static void PrintResultOrError<T>(string op, Func<Task<T>> f)
    {
        try
        {
            T result = f().GetAwaiter().GetResult();
            Console.WriteLine($"{op}: {result}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"{op} failed: {GetExceptionDescriptionWithInnerExceptions(e)}");
        }
    }
    public static void Main(string[] args)
    {
        Console.WriteLine("== Write after complete, unbounded without exception ==");
        TestChannelWriteAfterCompleted(false, null);
        Console.WriteLine();
        Console.WriteLine("== Write after complete, unbounded with exception ==");
        TestChannelWriteAfterCompleted(false, new Exception("Foobar!"));
        Console.WriteLine("== Write after complete, bounded without exception ==");
        TestChannelWriteAfterCompleted(true, null);
        Console.WriteLine();
        Console.WriteLine("== Write after complete, bounded with exception ==");
        TestChannelWriteAfterCompleted(true, new Exception("Foobar!"));
    }

    private static void TestChannelWriteAfterCompleted(bool bounded, Exception? exception)
    {
        Channel<string> channel = bounded ?
            Channel.CreateBounded<string>(new BoundedChannelOptions(5) { FullMode = BoundedChannelFullMode.Wait, SingleReader = true, SingleWriter = true }) :
            Channel.CreateUnbounded<string>(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true });
        channel.Writer.Complete(exception);
        PrintResultOrError("TryWrite", () => channel.Writer.TryWrite("Hello, World!"));
        PrintResultOrError("WaitToWriteAsync", () => channel.Writer.WaitToWriteAsync().AsTask());
        PrintResultOrError("WriteAsync", () => channel.Writer.WriteAsync("World").AsTask());
    }
}
Test program output
== Write after complete, unbounded with exception ==
TryWrite: False
WaitToWriteAsync failed: System.Exception: Foobar!
WriteAsync failed: System.Threading.Channels.ChannelClosedException: The channel has been closed.  ---> System.Exception: Foobar!
== Write after complete, bounded without exception ==
TryWrite: False
WaitToWriteAsync: False
WriteAsync failed: System.Threading.Channels.ChannelClosedException: The channel has been closed.

== Write after complete, bounded with exception ==
TryWrite: False
WaitToWriteAsync failed: System.Exception: Foobar!
WriteAsync failed: System.Threading.Channels.ChannelClosedException: The channel has been closed.  ---> System.Exception: Foobar!

Documentation source: https://github.com/dotnet/dotnet-api-docs/blob/main/xml/System.Threading.Channels/ChannelWriter%601.xml

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0