Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将其转换为异步等待代码并仅使用1个线程?_C#_.net_Asynchronous_Async Await - Fatal编程技术网

C# 如何将其转换为异步等待代码并仅使用1个线程?

C# 如何将其转换为异步等待代码并仅使用1个线程?,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我有一段代码,比如 public static void Main() { Console.WriteLine("Press any key to print 'Hello, world!' after 2 seconds"); while(true) { Console.ReadKey(); Task.Run(() => { Thread.Sleep(2000); C

我有一段代码,比如

public static void Main()
{
    Console.WriteLine("Press any key to print 'Hello, world!' after 2 seconds");
    while(true)
    {
        Console.ReadKey();
        Task.Run(() => 
        {
            Thread.Sleep(2000);
            Console.WriteLine(string.Format("Hello world! (from thread {0})", Thread.CurrentThread.ManagedThreadId);
        });
    }
}
当然,如果我快速按键,会创建很多线程,而这些线程除了等待使用它们的前2秒之外什么都不做

我想将动作更改为

await Task.Delay(2000).ConfigureAwait(false);

但我不知道如何将
async
-
wait
s“一路向上”链接起来以使其工作

您的需求并不完全清楚(您真的不需要使用额外的线程吗?使用
Task.Delay()
是您的目标的一个组成部分吗?),也不清楚您在具体理解什么方面遇到了困难

如果您可以接受少量的额外线程,那么
Task.Delay()
将适合您。当然,您需要使用
async
方法来等待它。IMHO,这在命名方法中比在匿名方法中更为正确:

public static void Main()
{
    Console.WriteLine("Press any key to print 'Hello, world!' after 2 seconds");
    while(true)
    {
        Console.ReadKey();
        KeyPressed();
    }
}

// WARNING: "async void" is discouraged!
private static async void KeyPressed()
{
    await Task.Delay(2000);
    Console.WriteLine(string.Format("Hello world! (from thread {0})", Thread.CurrentThread.ManagedThreadId);
}
注:

  • 对于
    async
    方法,使用
    void
    通常不是一个好主意。但在您的示例中,不太可能出现异常,而且您似乎也不想等待方法的完成,因此我还是使用
    void
    编写了上面的内容。在你的真实场景中,仔细考虑这是否真的合适。至少,如果可能发生异常,那么应该在
    async
    方法中放置
    try
    /
    catch
    处理程序,以确保观察到异常
  • 在控制台程序中,不需要使用
    ConfigureAwait()
    ,因为您没有一个同步上下文,无法在第一时间继续。将在线程池中继续
  • 以上并不是字面上的“只使用一个线程”。因为(正如我刚才提到的)延续发生在线程池中(没有返回主线程的机制),所以仍然会使用额外的线程。但是,它应该比您以前使用的数字少,因为只有在继续时才需要线程。延迟是使用一个计时器线程发生的(好吧,这里还有一个线程……但这是所有计时器共享的)。这种方法很可能只涉及少数额外线程,不管您按键的频率有多高

我看不到任何方法可以将解决方案简化为一个线程(即,一个用户创建的线程….NET在您背后创建线程,因此您永远不会真正拥有一个只有一个线程的.NET进程),除非您使用轮询而不是
ReadKey()
方法进行输入。这是可以做到的,但这将是一个非常低效的CPU时间使用。总之,
async
/
await
方法在简单性和效率之间取得了最佳平衡。

Task.Run(async()=>
?为了能够使用
await
,您需要将该操作作为一个异步操作。@Fildor只是在更短的时间内使用额外的线程,它仍然在使用额外的线程(不必要的)尽管如此。@Servy我只解决了“我想将操作更改为让
等待任务。延迟…”-部分,是的。因此不是答案。在控制台应用程序中,异步单线程代码有点棘手。您能解释一下为什么要这样做吗?通常,在GUI场景中,您会尝试使代码与一个线程密切相关,而不是控制台场景。