0

Hi I'm trying to make a simple code to run my function in async way. But the result turn out to be quite unexpected. the result i want is like the counter function can run in parallel way and output the result some way similar like:

Start1

End1

Start2

End2

Start3

Start4

End 3

......

Hi

but it turns out it only get the for loop value i=60 into counter function. I'm quite new to async method and google also cant find the appropriate explanation.

namespace Asycn
{
   class Program
   {
       static async Task Main(string[] args)
       {
           var tasks = new List<Task>();
           for (int i = 0; i < 60; i++)
           {
               tasks.Add(Task.Run(()=>counters(i)));
           }

           await Task.WhenAll(tasks);
           Console.WriteLine("Hi");

       }

       private static void counters(int num)
       {
           Console.WriteLine("Start"+num.ToString());
           Thread.Sleep(num*1000);
           Console.WriteLine("End"+num.ToString());
       }
   }

}

And below is the running result Running Result

Shepherd
  • 19
  • 2
  • Also, just as a tip, it's [much more helpful](http://idownvotedbecau.se/imageofcode) to us to include text as actual text (rather than as an image), since not everyone can read images for a variety of reasons. – EJoshuaS - Stand with Ukraine Aug 13 '20 at 15:58

2 Answers2

2

I assume that you are just getting familiar with async here. Generally when you want to process this number of tasks, it's better to limit parallelism with something like plinq, or Parallel.Foreach

The issue is that i is incremented before the Tasks run. All you need to do is capture the value within the loop:

namespace Asycn
{
   class Program
   {
       static async Task Main(string[] args)
       {
           var tasks = new List<Task>();
           for (int i = 0; i < 60; i++)
           {
               var copy = i; // capture state of i
               tasks.Add(Task.Run(()=>counters(copy)));
           }

           await Task.WhenAll(tasks);
           Console.WriteLine("Hi");

       }

       private static void counters(int num)
       {
           Console.WriteLine("Start"+num.ToString());
           Thread.Sleep(num*1000);
           Console.WriteLine("End"+num.ToString());
       }
   }

}
Jason
  • 1,505
  • 5
  • 9
0

Your code isn't actually using async/await to its fullest potential. You're not capturing the value of i, but you won't have to if you write your code like this:

static async Task Main(string[] args)
{
    var tasks = new List<Task>();
    for (int i = 0; i < 60; i++)
    {
        tasks.Add(counters(i));
    }

    await Task.WhenAll(tasks);
    Console.WriteLine("Hi");
}

private static async Task counters(int num)
{
    Console.WriteLine("Start"+num.ToString());
    await Task.Delay(num*1000);
    Console.WriteLine("End"+num.ToString());
}

The output looks like this:

Start0
End0
Start1
Start2
Start3
...
End1
End2
End3
...
Hi
Rudey
  • 4,717
  • 4
  • 42
  • 84