Returning an async computation expression as Task in .NET Generic Host IHostedService

I’m implementing the .NET Generic Host IHostedService interface in an F# console app. in the StartAsync method, I want to make an async call via HttpClient, so I have wrapped the body of the method in an async computation expression. However, I’m not sure how to return the computation expression as a Task to match StartAsync's expected return type.

As you can see, I have piped the async computation expression into Async.StartAsTask, and then explicitly cast that as a Task. This feels clunky to me. Is there a better way?

module CustomHostedService

    open Microsoft.Extensions.Hosting
    open System.Threading.Tasks
    open System.Net.Http
    open System

    type CustomHostedService(httpClientFactory: IHttpClientFactory, appLifetime: IApplicationLifetime) =

        let _httpClient = httpClientFactory.CreateClient()
        let _appLifetime = appLifetime

        interface IHostedService with

            member this.StartAsync(cancellationToken: System.Threading.CancellationToken): System.Threading.Tasks.Task = 
                async {

                    printfn "Starting service..."

                    use requestMsg = new HttpRequestMessage(HttpMethod.Get, "https://www.microsoft.com")

                    // Set per-request state
                    requestMsg.Properties.["CustomerId"] <- Guid.Parse("cc37bdc9-37c7-47d2-b8ad-dcbf6f691471");

                    // Execute the request.
                    use! response = _httpClient.SendAsync(requestMsg) |> Async.AwaitTask

                    // Do something with the response

                    // We're done. Tell the application to shut down.
                    _appLifetime.StopApplication()

                } |> Async.StartAsTask :> Task


            member this.StopAsync(cancellationToken: System.Threading.CancellationToken): System.Threading.Tasks.Task = 
                printfn "Stopping service..."
                Task.CompletedTask
1 Like

You could use a TaskBuilder package: https://github.com/rspeele/TaskBuilder.fs

I think something like that is being considered for inclusion in a future version of F#.

2 Likes

@mbuhot That’s awesome. Thanks for the pointer.

1 Like