Home
Options

How to wait for Dump() of IAsyncEnumerable?

I'm not sure if this is a LINQPad question or a matter of understanding how to use IAsyncEnumerable, but the following code throws an ObjectDisposedException:

void Main()
{
    using (var foo = new Foo())
    {
        foo.RangeAsync(10, 20)
            //.ToBlockingEnumerable()
            .Dump();
    }
}

class Foo : IDisposable
{
    private bool _disposed = false;

    public async IAsyncEnumerable<int> RangeAsync(int start, int count)
    {
        for (int i = 0; i < count; i++)
        {
            if(_disposed)
            {
                throw new ObjectDisposedException("Foo");
            }
            await Task.Delay(i * 1000);
            yield return start + i;
        }
    }

    public void Dispose()
    {
        _disposed = true;
    }
}

The only way to avoid this is to uncomment the .ToBlockingEnumerable() line, but then obviously nothing is Dump()ed until the whole enumerable has been returned. I would prefer to see the results as they are returned by RangeAsync.
Is there a way to make this work?

Comments

  • Options

    Also, there is an error message "limit of graph" after 1,0000 results, but there is no way to view the data in a grid instead...

  • Options

    The Dump methods always return the input - this is so that you can inject a Dump() into the middle of an expression and use it fluently.

    However, in this scenario, you need a version of Dump that returns a task that completes when the IAsyncEnumerable has completed, so that you can await it.

    This is not too difficult to write. Go to the My Extensions query and add the following:

    static class MyExtensions
    {
        public static Task DumpAsync<T> (this IAsyncEnumerable<T> input, string description = null)
            => DumpAsync (input, false, description);
    
        public static Task DumpAsync<T> (this IAsyncEnumerable<T> input, bool toDataGrid, string description = null)
        {
            var tcs = new TaskCompletionSource();
            Enumerate().Dump (toDataGrid, description);
            return tcs.Task;
    
            async IAsyncEnumerable<T> Enumerate()
            {
                await foreach (var item in input)
                    yield return item;
    
                tcs.SetResult();
            }
        }
    }
    

    Then you can call it as follows:

    async Task Main()
    {
    using (var foo = new Foo())
    {
    await foo.RangeAsync (10, 20).DumpAsync();
    }
    }

    Regarding your second question, LINQPad supports dumping IAsyncEnumerable to DataGrids. Either call Dump(true) or click the button on the toolbar to dump to DataGrids.

  • Options

    Nice, thank you! Maybe you could add DumpAsync as a native LINQPad method?

    When I export to a DataGrid, Hyperlinqs are rendered as text. Is there a way to keep them as links? I'd like to have links in my Excel output.

Sign In or Register to comment.