等价于 F# 中的 C# async main

Equivalent of C# async main in F#

我想知道什么与 F# 中的 C# 异步 main 等效。更重要的是,在 F# 程序中是否有来自 main 的 consuming/using 异步方法的特殊方式,还是只是等待完成的问题?

更具体地说,假设我们正在使用 .NET Core 通用主机。

在 C# 程序中,main 可能如下所示:

class Program
{
    static async Task Main(string[] args)
    {
         await new HostBuilder().Build().RunAsync();
    }
}

在 F# 程序中,我的直觉是做这样的事情:

[<EntryPoint>]
let main args =
    HostBuilder().Build.RunAsync().Wait()

...或...

[<EntryPoint>]
let main args =
    HostBuilder().Build.RunAsync() |> Async.AwaitTask |> Async.RunSynchronously

...或...

[<EntryPoint>]
let main args = 
    async {
        return HostBuilder().Build.RunAsync() |> Async.AwaitTask
    } |> Async.RunSynchronously

...或者只是避免异步...但这并不好玩...

[<EntryPoint>]
let main args =
    HostBuilder().Build.Run()

我可以展示更多的表述,但我认为这些表述很重要。

我想部分答案在于回答这些其他问题

  1. "what does it mean to run an async main method" 和
  2. "what's the point of making main async?"

举个例子,异步 main 似乎主要是为了让其他地方有可能以异步方式调用 main (在那些 main 不是真正的情况下"main",即单元测试等)。

在 F# 的情况下,我想至少有两件事阻止一个人从 return 进行异步计算 main:

  1. EntryPointAttribute 为状态代码强制执行 int return 类型...对吗?
  2. 编译器可能不准备将异步计算作为程序的退出值来处理...对吗?

据我所知,F# 中没有 async main 等价物。

如果您查看幕后的 C# 实现,它看起来像这样:

private static void <Main>(string[] args)
{
   Program.Main(args).GetAwaiter().GetResult();
}

Program.Main 是异步主线程。

我个人觉得这个模式有点可怕,具体取决于使用的 SynchronizationContext。

为了模拟 async main,我会:

let theAsyncTask : Async<int> = ...

[<EntryPoint>]
let main argv =
  async {
    do! Async.SwitchToThreadPool ()
    return! theAsyncTask
  } |> Async.RunSynchronously

theAsyncTask是实际要做的工作,嵌入的async切换到线程池,这样main线程就可以安全地阻塞等待结果。