等效于F#中的C#异步主体

时间:2019-03-17 15:53:57

标签: f# async-await f#-async

我想知道F#中的C#异步main相当于什么。更重要的是,在F#程序中是否有一种特殊的方法来使用/使用main中的异步方法,还是只是等待完成?

更具体地说,假设我们正在使用.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. “运行异步main方法意味着什么”和
  2. “实现主要异步的目的是什么?”

通过示例来看,异步main似乎主要是为了使其他地方可以异步方式调用main(在main并非真正“主要”的情况下”,即单元测试等)。

对于F#,我想至少有两件事阻止一个人仅从main返回异步计算:

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

1 个答案:

答案 0 :(得分:7)

AFAIK在F#中没有异步主要等效项。

如果您在后台查看C#实现,则它看起来像这样:

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

Program.Main是异步main。

我个人认为,根据使用哪种SynchronizationContext,这种模式会有些吓人。

要模拟异步主服务器,我将:

let theAsyncTask : Async<int> = ...

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

theAsyncTask是要完成的实际工作,嵌入式async切换到线程池,以便main线程可以安全地阻塞并等待结果。