StephenCleary/AsyncEx

Using `AsyncLock` magically causes tasks to complete

rick-micpoint opened this issue · 1 comments

The following function should never return, but it does, somehow. At no point does it throw an exception, but it still manages to complete the task. I tried to debug it but I have no idea how this is even possible, so here is a minimal reproducable example:

public async Task StressTest()
{
    var testLock = new AsyncLock();

    var tasks = Enumerable.Range(0, 100)
        .Select(taskIndex => Task.Factory.StartNew(async () =>
        {
            while (true)
            {
                using var _ = await testLock.LockAsync();
            }
        }, TaskCreationOptions.LongRunning))
        .ToArray();

    await Task.WhenAll(tasks);
}

This was tested on .NET 8, running on Windows.

Your problem is actually due to Task.Factory.StartNew. That method should not be used with async delegates.

More info: https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html

To correct the code, use Task.Run instead of Task.Factory.StartNew. Task.Run doesn't support the LongRunning flag, but that's perfectly fine because the LongRunning flag is useless in this case anyway (it doesn't do what you think it does).