我创建了 2 个打印 x 和 y 100 次的方法。我希望它们并发运行,并且我希望输出为 xxxyxyxyyyxyyxyx... 之类的。 它不打印任何东西。我在这里缺少一些逻辑吗?
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();
}
}
}
我们需要调整一些事情才能获得所需的输出:
xxxxyxyxyyyxyyxyx
。
Run
方法不等待Task i
和Task k
完成
Task
完成之前关闭Console.ReadLine()
,它将阻止控制台应用程序在字符串打印到屏幕上之前关闭。 Task.WhenAll
。 Task.WhenAll
将允许代码屈服于其调用线程(在本例中为主线程),该线程不会冻结应用程序的 UI,并允许应用程序继续打印到屏幕,直到 Task
已完成完全的。对于一个简单的控制台应用程序来说,这似乎微不足道,但在构建任何用户交互应用程序(如移动或 Web 应用程序)时,永远不要锁定主线程至关重要;锁定主线程是导致应用程序“冻结”的原因。Task.WaitAll
。这也是不好的做法,因为它也会冻结应用程序; Task.WaitAll
不可等待,并且不能屈服于调用线程。 Print1()
和 Print2()
永远不会屈服于主线程
await
内部的
for loop
await
内部需要一个for loop
,以允许CPU继续执行主线程,因为Console.Write()
只能在主线程上打印到屏幕。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();
}
}
}
xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxxyxyxyxy 按任意键继续...
C# 7.1 引入了
async Main
方法的功能。这意味着我们可以调整 Main
方法,如下所示:
...
private static async Task Main(string[] args)
{
await Run();
}
...
尝试了你的代码并且工作得很好。您可能认为它不起作用,因为控制台窗口关闭得非常快。在 Main 中添加
Console.ReadLine()
:
private static void Main(string[] args)
{
Run();
Console.ReadLine();
}
问题是您没有等待任务完成,因此程序正在终止(不再有同步代码阻塞)。
如果您希望任务同时运行,请执行以下操作:
public static void Run()
{
Task<int> i = Print1();
Task<int> k = Print2();
Task.WaitAll(i, k);
}
等待此任务完成的另一种方法是执行以下操作:
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();
}