theraot / Theraot

Backporting .NET and more: LINQ expressions in .net 2.0 - nuget Theraot.Core available.
MIT License
162 stars 30 forks source link

fix: Task.Run infinite Wait #192

Open workgroupengineering opened 2 years ago

workgroupengineering commented 2 years ago

If run code like this:


        [Test]
        [Category("Core")]
        public async Task ThreadSafeAsync()
        {
            // use a lot of threads to increase the likelihood of errors
            var concurrency = 100;

            var pool = new StringBuilderPool();
            var gate = new TaskCompletionSource<bool>();
            var startedTasks = new Task[concurrency];
            var completedTasks = new Task<string>[concurrency];
            for (int i = 0; i < concurrency; i++)
            {
                var started = new TaskCompletionSource<bool>();
                startedTasks[i] = started.Task;
                var captured = i;
                completedTasks[i] = Task.Run(async () =>
                {
                    started.SetResult(true);
                    await gate.Task;
                    var builder = pool.Rent();
                    builder.Append("Hello ");
                    builder.Append(captured);
                    var str = builder.ToString();
                    pool.Return(builder);
                    return str;
                });
            }

            // make sure all the threads have started
            await Task.WhenAll(startedTasks);

            // let them all loose at the same time
            gate.SetResult(true);

            // make sure every thread produces the expected string and hence had its own StringBuilder
            var results = await Task.WhenAll(completedTasks);
            for (int i = 0; i < concurrency; i++)
            {
                var result = results[i];
                Assert.AreEqual($"Hello {i}", result);
            }
        }