首页 > 解决方案 > C# 如何在命令行应用程序中使用异步方法运行线程

问题描述

我只是不知道如何使以下代码工作,假设在无限循环中永远运行,实际上当我await Task.Delay从方法中删除时它会工作Method_FOO,但我需要Method_FOO异步。

我认为要使这项工作,该Thread.Start()方法需要是“可等待的”(不仅仅是它运行的代码),但 Thread.Start 是无效的。我注意到,如果我用 eg.: 阻止执行,Console.ReadLine它将打印Worked字符串,但这不是解决方案,在现实生活中很糟糕。

这段代码只是一个例子,但是线程需要在无限循环中运行(这不是我可以改变的),并且我需要异步方法,因为我需要消耗一些 websocket,并且看起来没有同步客户端 websocket 类在 C# 中。

但是,对于这个问题,必须有一个简单/体面的解决方案。

public static class Program
{
    public static async Task Main(string[] args)
    {
        var cancellationTokenSource = new CancellationTokenSource();
        var thread1 = new Thread(async () => await Run(cancellationTokenSource.Token, "threadName1", Method_FOO));
        var thread2 = new Thread(async () => await Run(cancellationTokenSource.Token, "threadName2", Method_FOO));

        thread1.Start();
        thread2.Start();
    }
    
    private static async Task Method_FOO(CancellationToken cancellationToken)
    {
        Console.WriteLine("It is called...");
        await Task.Delay(300, cancellationToken); 
        //never reach this part
        Console.WriteLine("Worked  ...");
    }

    // workd but it is not async
    //private static  Task Method_FOO(CancellationToken cancellationToken)
    //{
    //    Console.WriteLine("It is called...");
    //   Console.WriteLine("Worked  ...");
    //    return Task.CompletedTask;
    //}


    private static async Task Run(CancellationToken cancellationToken, string threadName, Func<CancellationToken, Task> function)
    {
        try
        {
            while (true)
            {
                await function(cancellationToken);
                Console.WriteLine($"{threadName} waiting ...");
                cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}

标签: c#multithreadinglambdaasync-await

解决方案


在历史的这一点上,new Thread它几乎只对 COM 互操作有用。在所有其他情况下,都有更好的解决方案。在这种情况下,您可以使用以下命令将工作发送到线程池Task.Run

public static async Task Main(string[] args)
{
  var cancellationTokenSource = new CancellationTokenSource();
  var task1 = Task.Run(async () => await Run(cancellationTokenSource.Token, "threadName1", Method_FOO));
  var task2 = Task.Run(async () => await Run(cancellationTokenSource.Token, "threadName2", Method_FOO));

  await Task.WhenAll(task1, task2);
}

推荐阅读