All Projects → rspeele → Taskbuilder.fs

rspeele / Taskbuilder.fs

Licence: other
F# computation expression builder for System.Threading.Tasks

Programming Languages

fsharp
127 projects

Projects that are alternatives of or similar to Taskbuilder.fs

Swimmer
🏊 Swimmer - An async task pooling and throttling utility for JS
Stars: ✭ 94 (-56.68%)
Mutual labels:  async, task, await
Asyncex
A helper library for async/await.
Stars: ✭ 2,794 (+1187.56%)
Mutual labels:  async, task, await
Asyncawaitbestpractices
Extensions for System.Threading.Tasks.Task and System.Threading.Tasks.ValueTask
Stars: ✭ 693 (+219.35%)
Mutual labels:  async, task, await
Async Retry
Retrying made simple, easy and async
Stars: ✭ 1,262 (+481.57%)
Mutual labels:  async, await
Rq
Simple job queues for Python
Stars: ✭ 8,065 (+3616.59%)
Mutual labels:  async, task
Emacs Async Await
Async/Await for Emacs
Stars: ✭ 47 (-78.34%)
Mutual labels:  async, await
Koahub Demo
koahub+async/await+mysql
Stars: ✭ 15 (-93.09%)
Mutual labels:  async, await
Alecrimasynckit
async and await for Swift.
Stars: ✭ 89 (-58.99%)
Mutual labels:  async, await
Magpie
🐦 Successor of my monkey Interpreter(support for class, linq, sql, net, http, fmt, json and A realtime syntax highlighting REPL).
Stars: ✭ 88 (-59.45%)
Mutual labels:  async, await
Fsharp.control.fusiontasks
F# Async workflow <--> .NET Task/ValueTask easy seamless interoperability library.
Stars: ✭ 101 (-53.46%)
Mutual labels:  async, task
Async
Easily run code asynchronously
Stars: ✭ 1,983 (+813.82%)
Mutual labels:  async, await
Breeze
Javascript async flow control manager
Stars: ✭ 38 (-82.49%)
Mutual labels:  async, await
Csp
Communicating Sequential Processes in JavaScript
Stars: ✭ 33 (-84.79%)
Mutual labels:  async, await
Flowa
🔥Service level control flow for Node.js
Stars: ✭ 66 (-69.59%)
Mutual labels:  async, task
Modern Async
A modern JavaScript tooling library for asynchronous operations using async/await and promises
Stars: ✭ 31 (-85.71%)
Mutual labels:  async, await
Mobc
A generic connection pool for Rust with async/await support
Stars: ✭ 141 (-35.02%)
Mutual labels:  async, await
Unityfx.async
Asynchronous operations (promises) for Unity3d.
Stars: ✭ 143 (-34.1%)
Mutual labels:  async, task
Hydra
⚡️ Lightweight full-featured Promises, Async & Await Library in Swift
Stars: ✭ 1,954 (+800.46%)
Mutual labels:  async, await
Fennel
A task queue library for Python and Redis
Stars: ✭ 24 (-88.94%)
Mutual labels:  async, task
Taskmanager
A simple、 light(only two file)、fast 、powerful 、easy to use 、easy to extend 、 Android Library To Manager your AsyncTask/Thread/CallBack Jobqueue ! 一个超级简单,易用,轻量级,快速的异步任务管理器,类似于AsyncTask,但是比AsyncTask更好用,更易控制,从此不再写Thread ! ^_^
Stars: ✭ 25 (-88.48%)
Mutual labels:  async, task

NuGet

About

This is a single-file project that implements a computation expression for writing Tasks in F#. It is free and unencumbered software released into the public domain.

F# comes with its own Async type and functions to convert back and forth between Async and Task, but this is a bit of a hassle -- especially since now that Task has language-level support in C# and VB.NET, it's the de facto standard for asynchrony on .NET. Additionally, F#'s Async behaves a little differently from Task, which can be confusing if you're used to the latter.

The goal of this computation expression builder is to let you write asynchronous blocks that behave just like async methods in C# do.

For example, this F# method:

open System
open System.IO
open System.Linq
open FSharp.Control.Tasks.V2

type X() =
  static member WriteFile() =
    task {
      do! Console.Out.WriteLineAsync("Enter a filename:")
      let! name = Console.In.ReadLineAsync()
      use file = File.CreateText(name)
      for i in Enumerable.Range(0, 100) do
        do! file.WriteLineAsync(String.Format("hello {0}", i))
      do! Console.Out.WriteLineAsync("Done")
      return name
    }

Should work exactly the same as this C# method:

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

class X
{
  public static async Task<string> WriteFile()
  {
    await Console.Out.WriteLineAsync("Enter a filename:");
    var name = await Console.In.ReadLineAsync();
    using (var file = File.CreateText(name))
    {
      foreach (var i in Enumerable.Range(0, 100))
      {
        await file.WriteLineAsync(String.Format("hello {0}", i));
      }
      await Console.Out.WriteLineAsync("Done");
      return name;
    }
  }
}

In practice there is a small performance hit compared to the C# version, because the C# compiler compiles each async method to a specialized state machine class, while TaskBuilder uses a general-purpose state machine and must chain together continuation functions to represent the computation. However, TaskBuilder should still be faster than using Task.ContinueWith or Async.StartAsTask.

Usage

This is public domain code. I encourage you to simply copy TaskBuilder.fs into your own project and use it as you see fit. It is not necessary to credit me or include any legal notice with your copy of the code.

The other files are tests which you do not need to copy (but again, you are free to do so).

Note that by default, if you open FSharp.Control.Tasks.V2, you'll get a task { ... } builder that behaves as closely to C#'s async methods as possible.

However, I have also included a version of the task { ... } builder under FSharp.Control.Tasks.V2.ContextInsensitive which makes one minor change: it will automatically call task.ConfigureAwait(false) on every task you await.

This can improve performance if you're writing library code or server-side code and don't need to interact with thread-unsafe things like Windows forms controls. If you're not sure whether you want to use this version of the builder, reading this MSDN article may help.

What you can bind with let!

As of 7a04419, you should be able to bind anything "awaitable" with let!.

This basically means any type that has:

  • task.GetAwaiter()
  • task.GetAwaiter().GetResult()
  • task.GetAwaiter().IsCompleted

When using FSharp.Control.Tasks.ContextInsensitive, you can also bind any type that has a task.ConfigureAwait(false) returning an "awaitable" type.

Tail calls are not optimized

In F# it is idiomatic to use tail recursion to implement loops more complex than a simple for or while.

This works with some computation expressions (like the built-in F# async builder), but not with TaskBuilder.fs. As far as I know it is not possible to make this work with TPL tasks. C# async/await function are not tail-call optimized either, so at least this is consistent.

To implement a loop that may iterate many times (or indefinitely), use a while loop instead of tail recursion.

For example:

DO ✓

let runPendingJobs() =
    task {
        let mutable anyPending = true
        while anyPending do
            let! jobToRun = checkForJob()
            match jobToRun with
            | None ->
                anyPending <- false
            | Some pendingJob ->
                do! pendingJob()
    }

DON'T ✖

let rec runPendingJobs() =
    task {
        let! jobToRun = checkForJob()
        match jobToRun with
        | None ->
            return ()
        | Some pendingJob ->
            do! pendingJob()
            return! runPendingJobs()
    }

What's the deal with the V2 module?

For a while, TaskBuilder.fs depended on a compiler behavior that was introduced in F# 4.1.

It wouldn't work with older compiler versions -- more accurately, it would work, but would be unpleasant to use because types would have to be explicitly annotated everywhere.

Thankfully, @gusty rewrote the builder classes and extension methods to work with all F# compiler versions.

But DLLs compiled using the old builder couldn't use the new builder code, since beneath the inline methods, there is a completely different set of classes and methods involved.

Therefore, the old code is still included for binary-compatibility, while the new code lives under the V2 namespace.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].