1

I don't understand why this test shows that the lambda has run a single time. I can only see how it might yield 0 or 10000. But only once? Ideally, I'd like ALL the tasks to be executed, just like the tooltip documentation on Task.WhenAll suggests.

    [Fact]
    public async Task FireLotsOfQueries()
    {
        var counter = 0;
        var taskList = Enumerable.Repeat(Task.Run(async () =>
        {
            ++counter;
            await Task.Delay(1000);
        }), 10000);
        await Task.WhenAll(taskList);
        Assert.Equal(10000, counter);
    }

Result:

Xunit.Sdk.EqualException: Assert.Equal() Failure Expected: 10000 Actual: 1

abatishchev
  • 98,240
  • 88
  • 296
  • 433
cocogorilla
  • 1,815
  • 14
  • 36
  • 2
    `++counter` is not thread safe, you need to use `Interlocked.Increment(ref counter);` if you want to update a int from multiple threads. – Scott Chamberlain Aug 24 '17 at 21:22
  • @ScottChamberlain Fortunately the code doesn't access it from multiple threads. If the code is changed to access `counter` from multiple threads at the same time then yes, that becomes an issue. – Servy Aug 24 '17 at 21:31

1 Answers1

9

The problem is you are not creating 1000 tasks. You are creating an enumerable that contains the same task 1000 times. Try this:

public async Task FireLotsOfQueries()
{
    var counter = 0;
    var taskList = Enumerable.Range(0, 10000)
        .Select(_=> Task.Run(async () =>
        {
            ++counter;
            await Task.Delay(1000);
        }));
    await Task.WhenAll(taskList);
    Assert.Equal(10000, counter);
}

You will definitely need some locking around counter as this version also fails, but counter will be a value closer to 10000.

rexcfnghk
  • 14,435
  • 1
  • 30
  • 57
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357