Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / F#
Tip/Trick

Ignoring Operation Result when using F# async Computation Expression

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
6 Mar 2019CPOL 8.5K   2   6
Simple pitfall where C# developers trying out F# might fail when writing async code

Using the Code

Consider this simple code downloading page contents using Puppeteer-sharp.

F#
let renderHtml = async {
    BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask |> ignore
    let options = LaunchOptions()
    options.Headless <- true
    let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask
    let! page = browser.NewPageAsync() |> Async.AwaitTask
    page.GoToAsync("https://i.ua") |> Async.AwaitTask |> ignore    
    return! page.GetContentAsync() |> Async.AwaitTask    
}

Since we actually don't care about download browser result, we naturally would expect that our line...

F#
BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask |> ignore

...would be equivalent to this C# code:

C#
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

However, when we execute the following method, we get Aggregate<wbr />Exception which in turn contains the following inner exception: "Chromium revision is not downloaded. Run BrowserFetcher.DownloadAsync or download Chromium manually". Seems like we've called...

F#
let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask

...without waiting for BrowserFetcher result.

And indeed, in order to await async call, we have to use let! construct. The code below works as expected:

F#
let renderHtml = async {
    let! _ = BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask
    let options = LaunchOptions()
    options.Headless <- true
    let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask
    let! page = browser.NewPageAsync() |> Async.AwaitTask
    let! _ = page.GoToAsync("https://i.ua") |> Async.AwaitTask    
    return! page.GetContentAsync() |> Async.AwaitTask    
}

Note how we use underscore to show that the variable value is ignored.

History

  • 6th March, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
Ukraine Ukraine
Team leader with 8 years of experience in the industry. Applying interest to a various range of topics such as .NET, Go, Typescript and software architecture.

Comments and Discussions

 
QuestionUse `do!` instead of `let! _ =` Pin
Sergey Tihon8-Mar-19 21:17
Sergey Tihon8-Mar-19 21:17 
AnswerRe: Use `do!` instead of `let! _ =` Pin
Bohdan Stupak14-Mar-19 23:23
professionalBohdan Stupak14-Mar-19 23:23 
GeneralRe: Use `do!` instead of `let! _ =` Pin
Member 1433153525-Apr-19 7:39
Member 1433153525-Apr-19 7:39 
GeneralRe: Use `do!` instead of `let! _ =` Pin
sergiokoval12-May-20 11:48
sergiokoval12-May-20 11:48 
QuestionYep Pin
Sacha Barber8-Mar-19 20:25
Sacha Barber8-Mar-19 20:25 
Ignore just means we dont care about return value

Ignore has bothing to do with waiting of tasks

You still need to use await to get the result or let the exceptuon flow

If you go back to your ignore example and looked at disassembled code you would see why yiu got aggregate exception

AnswerRe: Yep Pin
Bohdan Stupak14-Mar-19 23:19
professionalBohdan Stupak14-Mar-19 23:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.