public async Task ThrowsOnSimultaneousInstanceUsage()
 {
     var sum        = 0;
     var lockObject = new object();
     var f          = new AsyncFor();
     var first      = f.RunFor(0, 10, async i =>
     {
         lock (lockObject)
         {
             sum += i;
         }
         await Task.Delay(100);
     });
     await Assert.ThrowsAsync <InvalidOperationException>(async() =>
     {
         await f.RunFor(0, 10, async i =>
         {
             lock (lockObject)
             {
                 sum += i;
             }
             await Task.Delay(100);
         });
     });
 }
        public async Task ReportsProgressThroughInstanceProperties()
        {
            var f = new AsyncFor();
            await f.RunFor(0, 6, i =>
            {
                Assert.False(f.IsCompleted);
                Assert.False(f.IsIndeterminate);
                Assert.True(f.Progress < 1);
            });

            Assert.True(f.IsCompleted);
            Assert.False(f.IsIndeterminate);
            Assert.Equal(1, f.Progress, precision: 1);
        }
        public async Task RunsForEveryNumberWithSynchronousDelegate_InstanceMethod()
        {
            var sum        = 0;
            var lockObject = new object();
            var f          = new AsyncFor();
            await f.RunFor(0, 10, i =>
            {
                lock (lockObject)
                {
                    sum += i;
                }
            });

            Assert.Equal(55, sum);
        }
        public async Task ReportsProgressThroughInstanceEvent()
        {
            var myCustomMessage   = $"Loading... ({Guid.NewGuid()})";
            var progressEventArgs = new ConcurrentBag <ProgressReportedEventArgs>();
            var completedCount    = 0;

            void OnProgressChanged(object sender, ProgressReportedEventArgs e)
            {
                progressEventArgs.Add(e);
                Assert.Equal(myCustomMessage, e.Message);
                Assert.False(e.IsIndeterminate);
                Assert.True(e.Progress <= 1);
            }

            void OnCompleted(object sender, EventArgs e)
            {
                Interlocked.Increment(ref completedCount);
            }

            var f = new AsyncFor();

            f.Message          = myCustomMessage;
            f.ProgressChanged += OnProgressChanged;
            f.Completed       += OnCompleted;
            f.BatchSize        = 2;
            await f.RunFor(1, 10, async data =>
            {
                await Task.CompletedTask;
            });

            f.ProgressChanged -= OnProgressChanged;
            f.Completed       -= OnCompleted;


            Assert.Equal(10, progressEventArgs.Count);
            Assert.Equal(1, completedCount);

            var distinctProgressPercentages = progressEventArgs.Select(e => e.Progress).Distinct().ToList();

            Assert.InRange(distinctProgressPercentages.Count, 2, 10);
            Assert.All(distinctProgressPercentages, p => Assert.InRange(p, 0, 1));
            Assert.Contains(distinctProgressPercentages, p => p != 0 && p != 1);
        }