I create 2 methods that print x and y 100 times. I want them to run concurrent and I expect the output to be xxxxyxyxyyyxyyxyx... sthg like that. It doesn't print anything. Am I missing some logic here?
using System;
using System.Threading.Tasks;
namespace ConsoleApplication32
{
internal class Program
{
public static async Task<int> Print1()
{
await Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Console.Write("x");
}
});
return 1;
}
public static async Task<int> Print2()
{
await Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Console.Write("y");
}
});
return 1;
}
public static void Run()
{
Task<int> i = Print1();
Task<int> k = Print2();
}
private static void Main(string[] args)
{
Run();
}
}
}
There are a couple things we need to tweak to get the desired output: xxxxyxyxyyyxyyxyx
.
The Run
method is not waiting for Task i
and Task k
to finish
Task
s complete Console.ReadLine()
, it will prevent the console application from closing before the strings have been printed to the screen. Task.WhenAll
. Task.WhenAll
will allow the code yield to its calling thread (in this case, the Main Thread) which doesn't freeze the UI of the application, and allows the application to continue to print to the screen until the Task
s have completed. This may seem trivial for a simple console app, but it is crucial to never lock up the Main Thread when building any user-interactive application like mobile or web applications; locking up the Main Thread is what causing apps to "freeze". Task.WaitAll
. This is also bad practice because it will also freeze the application; Task.WaitAll
is not awaitable and cannot not yield to the calling thread. Print1()
and Print2()
never yield to the Main Thread
await
inside of the for loop
await
is necessary inside of the for loop
to allow CPU to continue executing the Main Thread, because Console.Write()
can only print to the screen on the Main Thread. using System;
using System.Threading.Tasks;
namespace ConsoleApplication32
{
internal class Program
{
public static async Task<int> Print1()
{
for (int i = 0; i < 100; i++)
{
Console.Write("x");
await Task.Delay(10);
}
return 1;
}
public static async Task<int> Print2()
{
for (int i = 0; i < 100; i++)
{
Console.Write("y");
await Task.Delay(10);
}
return 1;
}
public static async Task Run()
{
var i = Print1();
var k = Print2();
await Task.WhenAll(i, k);
}
private static void Main(string[] args)
{
Task.Run(async () => await Run()).GetAwaiter().GetResult();
}
}
}
xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxxyxyxyxy Press any key to continue...
C# 7.1 introduces the ability to have an async Main
method. This means that we can tweak the Main
method as follows:
...
private static async Task Main(string[] args)
{
await Run();
}
...
Tried your code and works just fine. Probably you think it doesn't work because the console window closes very fast. Add a Console.ReadLine()
in your Main:
private static void Main(string[] args)
{
Run();
Console.ReadLine();
}
The problem is that you are not waiting for the tasks to complete, hence the program is terminating (no more synchronous code blocking).
If you want the tasks to run concurrently, do this instead:
public static void Run()
{
Task<int> i = Print1();
Task<int> k = Print2();
Task.WaitAll(i, k);
}
The other way to wait for this tasks to complete, would be to do this:
public static async Task Run()
{
Task<int> i = Print1();
Task<int> k = Print2();
await Task.WhenAll(i, k);
}
public static void Main(string[] args)
{
Run().GetAwaiter().GetResult();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.