【发布时间】:2021-05-12 02:37:41
【问题描述】:
我想制作一个 C# 控制台应用程序,它可以在执行某些工作时评估用户输入。为此,我想等待类似于此的输入异步:await Console.ReadLine()。出于测试目的,我只是希望主工作循环在我按 Enter 时停止运行。我是这样实现的:
using System;
using System.Threading;
using System.Threading.Tasks;
class WorkTillEnter
{
private static bool running = false;
public static void Main(string[] args)
{
WorkTillEnter.running = true;
WorkTillEnter.observeInputAsync();
DateTime lastTick = DateTime.Now;
while(WorkTillEnter.running){
if(lastTick.Second != DateTime.Now.Second){
Console.WriteLine($"Tick {DateTime.Now}");
lastTick = DateTime.Now;
}
//Doing Work in this loop until enter is hit
}
Console.WriteLine("Worker Terminated.");
}
private static async void observeInputAsync(){
await Task.Delay(1); // <--WHY???
await Console.In.ReadLineAsync();
WorkTillEnter.running = false;
}
}
这可以正常工作,并且每秒打印一次 Ticks,直到按下 Enter。 我现在的问题是:为什么我删除了这一行后不起作用? await Task.Delay(1); // <--WHY??? 没有这一行,程序什么也不做,直到我点击返回,然后显然永远不会进入 while 循环。如何解释这种行为?
这个建议Why does Console.In.ReadLineAsync block? 解释了为什么当我的可疑线路被删除时Console.In.ReadLineAsync 的行为不符合预期。但它没有解释为什么它在添加 Line 时实际上表现得如预期。
【问题讨论】:
-
这有点回答了为什么
Console.In.ReadLineAsync()的行为不像预期的那样,当我在问题中的行被删除时。但不是为什么它实际上表现得像我预期的那样。 -
那是因为当该行不在其中时,所有内容都在同一个线程上运行。因此读操作是阻塞的。如果它在那里,运行时决定在两个不同的线程上运行它。只需记录 Thread.CurrentThread.ManagedThreadId。猜猜这归结为运行时的优化。如果它不会阻塞,则应该没有死锁的理由。
-
啊,所以实际工作的等待会导致异步函数被推送到不同的线程!谢谢,解释了一切。
-
好吧,在这种情况下是的 - 我不保证情况总是如此。如果 read 方法真的是异步的,那么如果所有东西都在同一个线程上运行,那也不是问题。
-
你也可以看看
static async Task Main——它可能会有所帮助
标签: c# asynchronous async-await console-application user-input