ReusableTasks 0.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package ReusableTasks --version 0.0.1
NuGet\Install-Package ReusableTasks -Version 0.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ReusableTasks" Version="0.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ReusableTasks --version 0.0.1
#r "nuget: ReusableTasks, 0.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ReusableTasks as a Cake Addin
#addin nuget:?package=ReusableTasks&version=0.0.1

// Install ReusableTasks as a Cake Tool
#tool nuget:?package=ReusableTasks&version=0.0.1

Introduction.

ReusableTasks provides three classes.

  • ReusableTask - a zero allocation Task-like object which can be used in place of System.Threading.Tasks.Task when declaring async methods.
  • ReusableTask<T> - a zero allocation Task-like object which can be used in place of System.Threading.Tasks.Task<T> when declaring async methods.
  • ReusableTaskCompletionSource<T> - a zero allocation TaskCompletionSource-like object, built on top of ReusableTask<T<>, which can be used in place of System.Threading.Tasks.TaskCompletionSource<T> in scenarios where you would normally repeatedly instantiate new copies of TaskCompletionSource<T>.

Migration examples:

Change your async method declarations as follows:

async Task Old ()
{
    await Task.Delay (100); // Do Stuff
}

async ReusableTask New ()
{
    await Task.Delay (100); // Do Stuff
}

async Task<int> Old ()
{
    await Task.Delay (100); // Do Stuff
    return 5;
}

async ReusableTask<int> New ()
{
    await Task.Delay (100); // Do Stuff
    return 5;
}

Limitations

The caching strategy employed by ReusableTask means you cannot await a task twice. This kind of code would either deadlock or cause corruption of the ReusableTask cache:

public async ReusableTask<int> CalculateAge ()
{
    await Task.Delay (100); // Do Stuff
    return 42;
}

async void CorruptCache ()
{
    var task = CalculateAge  ();
    Task.Run (async () => await task);
    Task.Run (async () => await task);
}

ReusableTaskCompletionSource<int> has the same limitation, the returned task should not have multiple concurrent awaits:

public async void CorruptTCS ()
{
    var tcs = new ReusableTaskCompletionSource<int> ();
    
    Task.Run (async () => await tcs.Task);
    Task.Run (async () => await tcs.Task);

    tcs.SetResult (5);
}

async void SafelyReuseTCS ()
{
    var tcs = new ReusableTaskCompletionSource<int> ();

    async void SetResultEverySecond ()
    {
        for (int i = 0; i < 100; i ++) {
            await Task.Delay (1000);
            tcs.SetResult (i);
        }
    }

    SetResultEverySecond ();
    while (true) {
         Console.WriteLine ("Current iteration is: {0}", await tcs.Task);
    }
}

NOTE: In real code you should ensure that the await completes before you invoke SetResult, SetException or SetCanceled a second time. This ensures that you never have two concurrent await calls.

public async ReusableTask<int> CalculateAge ()
{
    return 42;
}

async void SafelyAwait ()
{
    var task = CalculateAge  ().AsTask ();
    await task;
    await task;
}

Real world benefits

MonoTorrent is currently testing a prototype of this approach and the benefits are pretty noticeable. More detailed profiling results are on the MonoTorrent pull request, but the latest results at the time of writing total allocations were reduced from 980MB to 210MB while downloading two 2GB torrents.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on ReusableTasks:

Package Downloads
MonoTorrent

MonoTorrent is a cross platform and open source implementation of the BitTorrent protocol. It supports many advanced features such as Encryption, DHT, Peer Exchange, Web Seeding and Magnet Links. Notable features include: -Encryption -Dht -Peer Exchange (uTorrent style) -Local Peer Discovery -Web Seeding (getright style) -Magnet Links / Metadata download -IPV6 -FAST Extensions -Sparse files (NTFS file system) -Multi-tracker torrents -Compact tracker responses -IP Address white listing / black listing -Fast Resume -Initial Seeding (super seeding) -Selective downloading -Prioritised downloading -Full bittorrent tracker -Dynamic request queue size -Memory Cache -Endgame mode -Per torrent and global rate limiting -Individual file relocation

DotProxify

Allows proxying TCP connections and UDP dgrams via a SOCKS5 proxy.

RaptureTorrent

MonoTorrent is a cross platform and open source implementation of the BitTorrent protocol. It supports many advanced features such as Encryption, DHT, Peer Exchange, Web Seeding and Magnet Links. Notable features include: -Encryption -Dht -Peer Exchange (uTorrent style) -Local Peer Discovery -Web Seeding (getright style) -Magnet Links / Metadata download -IPV6 -FAST Extensions -Sparse files (NTFS file system) -Multi-tracker torrents -Compact tracker responses -IP Address white listing / black listing -Fast Resume -Initial Seeding (super seeding) -Selective downloading -Prioritised downloading -Full bittorrent tracker -Dynamic request queue size -Memory Cache -Endgame mode -Per torrent and global rate limiting -Individual file relocation

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on ReusableTasks:

Repository Stars
alanmcgovern/monotorrent
The official repository for MonoTorrent, a bittorrent library for .NET
IllusionMods/KKManager
Mod, plugin and card manager for games by Illusion that use BepInEx
Version Downloads Last updated
2.0.2 6,480 3/28/2022
2.0.1 1,887 11/6/2021
2.0.0 447,203 5/18/2020
1.0.8 923 5/18/2020
1.0.7 8,957 4/25/2020
1.0.6 35,372 12/2/2019
1.0.6-beta 1,398 11/28/2019
1.0.5 1,892 11/17/2019
1.0.4 839 11/17/2019
1.0.3 898 11/13/2019
1.0.2 952 11/11/2019
1.0.1 1,817 11/2/2019
1.0.0 1,797 11/1/2019
0.99.4 2,562 10/30/2019
0.99.3 947 10/30/2019
0.99.1 913 10/29/2019
0.99.0 912 10/29/2019
0.0.1 947 10/28/2019