[RFC FS-1021 Discussion] Support Interop with ValueTask in Async Type #118
Replies: 19 comments 1 reply
-
The only question I have is if the type signatures in the Proposed Design can be written as-described or if it would need to change to remove the optional parameters. Specifically, the optional I wrote that initial design so that it would match the signatures of @stephentoub does this sound correct? If figure you'd be the best person to ask for guidance here 😄. |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Added this comment #119 @stephentoub Where is ValueTask to be defined? |
Beta Was this translation helpful? Give feedback.
-
Right now it's in the System.Threading.Tasks.Extensions.dll assembly: I wouldn't be surprised if it moved down into mscorlib.dll, System.Private.Corelib.dll, etc. in time, but that'll take some time to get it into all of the relevant platforms. The NuGet package can be consumed today to get the type. |
Beta Was this translation helpful? Give feedback.
-
@stephentoub thanks @cartermp I'm pretty keen that using FSharp.Core doesn't induce transitive dependencies on more DLLs apart from some "very core" ones. This is especially true on .NET Framework. For example, we are working pretty hard to ensure that the struct tuples work doesn't induce a static dependency of FSharp.Core.dll on System.ValueTuple.dll. We also have a lingering static dependency on System.Console.dll which looks like it may be problematic. |
Beta Was this translation helpful? Give feedback.
-
@dsyme When you say static dependency, are you referring to a fixed version of the NuGet package, or an embedded This could also just be a point in time problem. It seems like most (if not all) of these transitive dependencies will eventually be present in the subset of mscorlib that will be available in the .NET Standard Library 2.0. |
Beta Was this translation helpful? Give feedback.
-
Yes. Blasting mscorlib.dll into many DLLs in .NET Standard 1.x hasn't helped solve the dependency management problem for FSharp.Core, as right now we have to decide which fragments we want to depend on! :) |
Beta Was this translation helpful? Give feedback.
-
I'm not sure I see the point in Async.StartAsValueTask - Creating a value task only adds benefit if the path can avoid creating objects to eliminate the GC pressure, which I don't believe would be possible in this case, since you'd always be generating a Task anyways, in addition to all of the objects required for supporting the async builders on the F# side. It seems like the focus should be on consumption, in which case, focusing on consuming based on the more general awaiter syntax seems like a much better approach, as it would also support other existing problematic points (like Task.Yield, dispatcher operations, etc, all of which are awaitable, but not Task/Task). Focusing on consumption also eliminates the need to reference ValueTask entirely - as the INotifyCompletion interfaces required are already in mscorlib. |
Beta Was this translation helpful? Give feedback.
-
@ReedCopsey Yeah, I'm not entirely enthusiastic about @dsyme Any ideas about what "Task-like" consumption would look like for Async? |
Beta Was this translation helpful? Give feedback.
-
@cartermp From my point of view, it'd ideally just be I'd have to look into whether this would be possible to support via statically resolved type parameters - if so, it should actually be a fairly simple change to FSharp.Core to make that work. |
Beta Was this translation helpful? Give feedback.
-
That's where I would start to look too. |
Beta Was this translation helpful? Give feedback.
-
I think that this feature can and should be implemented not in FSharp.Core but in the separate NuGet package instead. |
Beta Was this translation helpful? Give feedback.
-
Hi! static member AwaitValueTask: task: ValueTask -> Async<unit> And I think having following functions too could be convenient (although they don't have Task counterparts): static member StartAsUnitValueTask : computation:Async<unit> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> ValueTask
static member StartChildAsUnitValueTask : computation:Async<unit> * ?taskCreationOptions:TaskCreationOptions -> Async<ValueTask>
static member RunValueTask : (CancellationToken -> ValueTask<'T>) * ?taskCreationOptions:TaskCreationOptions -> Async<'T>
static member RunValueTask : (CancellationToken -> ValueTask) * ?taskCreationOptions:TaskCreationOptions -> Async<unit> Also there's a capitalization mistype in "StartChildAsvalueTask" function name. |
Beta Was this translation helpful? Give feedback.
-
static member AwaitValueTask: task: ValueTask<'T> -> Async<'T> Fyi, this method must thunk the
If any method should be added it is: static member AwaitValueTask: task: (unit -> ValueTask<'T>) -> Async<'T> This would be setting the expectation any caller should always be returning fresh |
Beta Was this translation helpful? Give feedback.
-
static member AwaitValueTask: task: (unit -> ValueTask<'T>) -> Async<'T> Yes, that was basically my idea behind RunValueTask above (plus to discourage forgetting about CancellationToken). I just pointed that if there would be AwaitValueTask for ValueTask<'T> then there should be one for ValueTask. Honestly, I think that regular AwaitTask is a bit dodgy for similar reason: reentering Async that does AwaitTask on the same Task/Task<'T> is formally not an error, but there's a fair chance that result would be not what programmer expected. If there would be 4 similar to above methods for regular Task I'd be happy. About added value: well, it rids programmers from writing same chunk of code again and again each time they're working with ValueTask (which may soon be reasonably often since ValueTask now in netstandard and a few nice libraries). And even it there would be just AsTask() there, there may be something smarter in the next version, which would immediately benefit everyone using Async with ValueTask. Although, more clear name may be a good idea. AwaitAndRememberValueTask? :) |
Beta Was this translation helpful? Give feedback.
-
This is still alive, please send PRs to adjust the rfc |
Beta Was this translation helpful? Give feedback.
-
If I understand correctly, that should exclude 4 functions I mentioned above as "convenient"? |
Beta Was this translation helpful? Give feedback.
-
We should totally use Async.AwaitValueTask, because calling .AsTask defeats performance, my streams needs disposing when I call fstream.DisposeAsync() and a lot other streams it returns a value task nowadays |
Beta Was this translation helpful? Give feedback.
-
For future reference, IcedTasks implements AwaitValueTask. Also, there is an asyncEx builder that can handle |
Beta Was this translation helpful? Give feedback.
-
Discussion thread for F# RFC FS-1021 - Support Interop with ValueTask in Async Type
Beta Was this translation helpful? Give feedback.
All reactions