Description
I propose we add two Async.AwaitTask
overloads:
Async.AwaitTask(makeTask: CancellationToken -> Task<'a>) -> Async<'a>
Async.AwaitTask(makeTask: CancellationToken -> Task) -> Async<unit>
I also propose that an accompanying compiler warning be added. In situations where the task method could have been provided a CancellationToken
(either via an optional parameter or a separate overload), the compiler should emit a warning.
The warning could say something like: "This task-returning method can accept a CancellationToken (through an overload or optional parameter), but is not provided one. Please either use Async.AwaitTask(makeTask: CancellationToken -> Task<'a>), or capture and provide a CancellationToken manually."
Surely there are better wordings for such a warning; improvements are welcome.
For example, the following, which forgets to pass a CancellationToken, would now emit a warning:
let doWorkBad () = async {
do! Async.AwaitTask (File.WriteAllTextAsync ("file.txt", "Hello, world!"))
}
To make the warning go away, you could use the new overload:
let doWorkGood () = async {
do! Async.AwaitTask (fun ct -> File.WriteAllTextAsync ("file.txt", "Hello, world!", ct))
}
Or capture and pass it yourself:
let doWork () = async {
let! ct = Async.CancellationToken
do! Async.AwaitTask (File.WriteAllTextAsync ("file.txt", "Hello, world!", ct))
}
The existing way of approaching this problem in F# is ...
For the new method, you can write your own extensions today:
type Async =
static member AwaitTask (makeTask: CancellationToken -> Task<'a>) = async {
let! ct = Async.CancellationToken
let! result = Async.AwaitTask (makeTask ct)
return result
}
static member AwaitTask (makeTask: CancellationToken -> Task) = async {
let! ct = Async.CancellationToken
let! result = Async.AwaitTask (makeTask ct)
return result
}
Pros and Cons
The advantages of making this adjustment to F# are:
- Makes it harder to forget to pass a CancellationToken when bridging from Async to Task code, which is a common source of bugs
- Makes it easier to do the actual passing of the CancellationToken (reduces common boilerplate)
The disadvantages of making this adjustment to F# are:
- More library and compiler complexity
Extra information
Estimated cost (XS, S, M, L, XL, XXL): S
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
- I have searched both open and closed suggestions on this site and believe this is not a duplicate
- This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.
Please tick all that apply:
- This is not a breaking change to the F# language design
- I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.