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
  • 95,331
  • 80
  • 293
  • 426
cocogorilla
  • 1,775
  • 12
  • 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

7

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
  • 12,915
  • 1
  • 31
  • 55
Titian Cernicova-Dragomir
  • 196,102
  • 20
  • 333
  • 303