So apparently .NET's brand new ValueTask<T> is the leaner version of Task<T>. That's cool, but if before I had to use Async.AwaitTask to integrate my F# Async workflows with Task, what should I do with ValueTask now?
So apparently .NET's brand new ValueTask<T> is the leaner version of Task<T>. That's cool, but if before I had to use Async.AwaitTask to integrate my F# Async workflows with Task, what should I do with ValueTask now?
Before Async.AwaitValueTask is implemented (thanks Aaron), one can use ValueTask's AsTask method, and use Async.AwaitTask for now, as the simplest solution.
My OSS project "FusionTasks" can handle naturally and implicitly interprets both Task and ValueTask same as F# Async type on F# async workflow:
let asyncTest = async {
use ms = new MemoryStream()
// FusionTasks directly interpreted Task class in F# async-workflow block.
do! ms.WriteAsync(data, 0, data.Length)
do ms.Position <- 0L
// FusionTasks directly interpreted Task<T> class in F# async-workflow block.
let! length = ms.ReadAsync(data2, 0, data2.Length)
do length |> should equal data2.Length
}
With the new task expressions, it is explained here: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/task-expressions#value-tasks
I just implemented a System.IAsyncDisposable which returns a System.Threading.Tasks.ValueTask like so:
interface IAsyncDisposable with
member _.DisposeAsync(): ValueTask =
task {
use _ = client
return ()
} |> ValueTask
You can see that I'm just piping the task to ValueTask.