Current | |
---|---|
NuGet Package (F# 2.0) | |
NuGet Package (F# 3.0) | |
NuGet Package (F# 3.1) | |
NuGet Package (F# 4.0) | |
NuGet Package (F# 4.0/.NET Core) | |
Continuous integration | |
Gitter |
- F# Async workflow <--> .NET Task/ValueTask easy seamless interoperability library.
- Sample codes (F# side):
let asyncTest = async {
use ms = new MemoryStream()
// FusionTasks directly interpreted System.Threading.Tasks.Task class in F# async-workflow block.
do! ms.WriteAsync(data, 0, data.Length)
do ms.Position <- 0L
// FusionTasks directly interpreted System.Threading.Tasks.Task<T> class in F# async-workflow block.
let! length = ms.ReadAsync(data2, 0, data2.Length)
do length |> should equal data2.Length
}
- Sample codes (C# side):
using System.Threading.Tasks;
using Microsoft.FSharp.Control;
public async Task AsyncTest(FSharpAsync<int> asyncIntComp)
{
// FusionTasks simple usage F#'s Async<unit> direct awaitable.
await FSharpAsync.Sleep(500);
Console.WriteLine("Awaited F# async function (unit).");
// FusionTasks simple usage F#'s Async<int> direct awaitable.
var result = await asyncIntComp;
Console.WriteLine("Awaited F# async function: Result=" + result);
}
- Easy interoperability .NET Task/ValueTask <--> F#'s Async.
- F# async workflow block now support direct .NET Task/ValueTask handle with let!, do! and use!.
- .NET (C# async-await) now support directly F#'s Async.
- SyncronizationContext capture operation support (F#: AsyncConfigure method / .NET (C#) AsAsyncConfigured method)
- Easy interoperability, combination and relation standard .NET OSS packages using Task/ValueTask and F#'s Async.
- F# 2.0, 3.0, 3.1 and 4.0 with .NET 4.0/4.5 include PCL Profile 7/47/78/259 and .NET Core 1.0 (.NET Standard 1.6 or higher).
- Ready to LINQPad 5.
- .NET Framework 4.0/4.5
- .NET Framework Portable class library (Profile 7/47/78/259)
- F# 2.0, 3.0, 3.1, 4.0 (NuGet package separated, choose one)
- .NET Core 1.0 (F# 4.0 only, .NET Standard 1.6 or higher)
- Currently, separated NuGet package (FS40.netcore) and must require -Pre option for use, because .NET Core version FSharp.Core.dll depends on System.Reflection.Metadata BETA package.
- Search NuGet package and install "FSharp.Control.FusionTasks.FS??". You must select F# version.
- F# use, autoopen'd namespace "FSharp.Control". "System.Threading.Tasks" is optional.
- C# use, using namespace "System.Threading.Tasks". "Microsoft.FSharp.Control" is optional.
let asyncTest = async {
use ms = new MemoryStream()
// FusionTasks directly interpreted System.Threading.Tasks.Task class in F# async-workflow block.
// Sure, non-generic Task mapping to Async<unit>.
do! ms.WriteAsync(data, 0, data.Length)
do ms.Position <- 0L
// FusionTasks directly interpreted System.Threading.Tasks.Task<T> class in F# async-workflow block.
// Standard usage, same as manually used Async.AwaitTask.
let! length = ms.ReadAsync(data2, 0, data2.Length)
do length |> should equal data2.Length
}
use ms = new MemoryStream()
// Manually conversion by "AsAsync" : Task<T> --> Async<'T>
let length = ms.ReadAsync(data, 0, data.Length).AsAsync() |> Async.RunSynchronosly
use ms = new MemoryStream()
let cts = new CancellationTokenSource()
// Produce with CancellationToken:
// TIPS: FusionTasks cannot handle directly CancellationToken IN ASYNC WORKFLOW.
// Because async workflow semantics implicitly handled CancellationToken with Async.DefaultCancellationToken, CancellationToken and CancelDefaultToken().
// (CancellationToken derived from Async.StartWithContinuations() in async workflow.)
let length = ms.ReadAsync(data, 0, data.Length).AsAsync(cts.Token) |> Async.RunSynchronosly
let asyncTest = async {
use ms = new MemoryStream()
// Task<T> --> ConfiguredAsyncAwaitable<'T> :
// Why use AsyncConfigure() instead ConfigureAwait() ?
// Because the "ConfiguredTaskAwaitable<T>" lack declare the TypeForwardedTo attribute in some PCL.
// If use AsyncConfigure(), complete hidden refer ConfiguredTaskAwaitable into FusionTasks assembly,
// avoid strange linking errors.
let! length = ms.ReadAsync(data, 0, data.Length).AsyncConfigure(false)
}
open System.Threading
let asyncCalculate() =
// Create AsyncCompletionSource<'T>.
let acs = new AsyncCompletionSource<int>()
// Execution with completely independent another thread...
let thread = new Thread(new ThreadStart(fun _ ->
Thread.Sleep(5000)
// If you captured thread context (normally continuation or callbacks),
// can delegation async continuation using AsyncCompletionSource<'T>.
acs.SetResult(123 * 456)))
thread.Start()
// Async<'T> instance
acs.Async
let asyncInner arg0 = async {
// Cause FS0041:
// A unique overload for method 'Source' could not be determined based on type information prior to this program point.
// A type annotation may be needed.
// --> Because F# compiler conflict arg0 type inferences: Async<int> or Task<int>.
let! result = arg0
let calculated = result + 1
printfn "%d" calculated
}
// Fixed with type annotation Async<'T> or Task<'T>:
let asyncInner (arg0:Async<_>) = async {
let! result = arg0
let calculated = result + 1
printfn "%d" calculated
}
- Really need sample codes? huh? :)
- Before setup NuGet package (FSharp.Control.FusionTasks.FS40) the LINQPad NuGet Manager.
open System.IO
// Result is Async<byte[]>
let asyncSequenceData =
let r = new Random()
let data = [| for i = 1 to 100 do yield byte (r.Next()) |]
async {
use fs = new MemoryStream()
do! fs.WriteAsync(data, 0, data.Length)
do! fs.FlushAsync()
return fs.ToArray()
}
// Convert to Task<byte[]> and dump:
asyncSequenceData.AsTask().Dump()
- .NET add new "task-like" type. "task-like" means applied a attribute "System.Runtime.CompilerServices.AsyncMethodBuilderAttribute" and declared the async method builder.
- ValueTask overview:
- New standard "task-like" type named for "ValueTask<T>" for C#. FusionTasks supported ValueTask<T> on 1.0.20.
- ValueTask<T> declared by struct (Value type) for goal is improvement performance. But this type has the Task<T> instance inside and finally continuation handle by Task<T>.
- ValueTask<T> performance effective situation maybe chatty-call fragments using both caller C# and awaiter C# codes...
- ValueTask<T> a little bit or no effect improvement performance, because usage of senario for FusionTasks.
- "task-like" augumenting is difficult:
- The attribute "AsyncMethodBuilderAttribute" must apply TARGET task-like type.
- Means if already declared type (Sure, we have FSharpAsync<'T>) cannot augument and cannot turn to task-like type.
- Therefore cannot directly return for FSharpAsync<'T> from C#'s async-await method.
- And cannot auto handle task-like type by FusionTasks, because no type safe declaration for task-like type...
- For example, if force support task-like type, FusionTasks require augument "Source: taskLike: obj -> FSharpAsync<'T>" overload on FSharpAsync<'T>. This cannot type safe.
- Conclusion:
- So FusionTasks support only "ValueTask<T>" type and cannot support any other "task-like" types.
- Source codes available only "FSharp.Control.FusionTasks" folder.
- The slides: "How to meets Async and Task" in Seattle F# Users group "MVP Summit Special: A Night of Lightning Talks" 2016.11.09 http://www.slideshare.net/kekyo/asyncs-vs-tasks
Improvements more easier/effective interfaces.
- Copyright (c) 2016 Kouji Matsui
- Under Apache v2 http://www.apache.org/licenses/LICENSE-2.0
- 1.0.20:
- Support ValueTask<T> (Exclude net40 and Profile 47 platform, added dependency for System.Threading.Tasks.Extensions).
- Update version for .NET Core F# (1.0.0-alpha-161205).
- 1.0.13:
- Reduce to only contains .NET Core's assembly in FS40.netcore package.
- Refactor folder structures.
- 1.0.12:
- Add .NET Core support (Separated package: FSharp.Control.FusionTasks.FS40.netcore with -Pre option required)
- 1.0.2:
- Support 'for .. in' expressions. (Thx Armin!)
- 1.0.1:
- Fixed cause undefined Async<'T> using combination Async<'T> and Task/Task<T> in async workflow. (Thx Honza!)
- 1.0.0:
- RTM release ๐
- Add FSharp.Core NuGet references.
- Temporary disable support .NET Core. If reached F# RTM, continue development... (PR welcome!!)
- Add sample codes.
- 0.9.6:
- WIP release.
- 0.9.5:
- WIP release.
- 0.9.4:
- Fixed nuspec reference System, System.Core
- 0.9.3:
- Fixed nuspec frameworkAssemblies.
- 0.9.2:
- Add package targetFramework.
- Updated RelaxVersioner.
- 0.9.1:
- Remove strongly-signed (Unit test doesn't work...)
- Omit synchronizers (AsyncLock, AsyncLazy). Thats moving to FSharp.Control.AsyncPrimitives project (https://github.com/kekyo/FSharp.Control.AsyncPrimitives).
- Add target dnxcore50 into F# 4.0 (for .NET Core 1.0)
- Source codes and documents bit changed.
- 0.5.8:
- Add strongly-signed.
- 0.5.7:
- Add PCL Profile 7.
- 0.5.6:
- Add PCL Profile 78.
- Fixed minor PCL moniker fragments.
- 0.5.5:
- Fixed version number.
- Fixed icon image url.
- 0.5.4:
- Auto open FSharp.Control.
- Manage AppVeyor CI.
- 0.5.3: Implement awaiter classes.
- 0.5.2: Add dependency assemblies.
- 0.5.1: NuGet package support.