ReusableTasks 0.0.1
See the version list below for details.
dotnet add package ReusableTasks --version 0.0.1
NuGet\Install-Package ReusableTasks -Version 0.0.1
<PackageReference Include="ReusableTasks" Version="0.0.1" />
paket add ReusableTasks --version 0.0.1
#r "nuget: ReusableTasks, 0.0.1"
// 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 ofSystem.Threading.Tasks.Task
when declaring async methods.ReusableTask<T>
- a zero allocation Task-like object which can be used in place ofSystem.Threading.Tasks.Task<T>
when declaring async methods.ReusableTaskCompletionSource<T>
- a zero allocation TaskCompletionSource-like object, built on top ofReusableTask<T<>
, which can be used in place ofSystem.Threading.Tasks.TaskCompletionSource<T>
in scenarios where you would normally repeatedly instantiate new copies ofTaskCompletionSource<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 | Versions 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. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages (2)
Showing the top 2 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. |
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 |
---|---|---|
4.0.0 | 3,067 | 6/29/2024 |
3.0.0 | 155 | 6/20/2024 |
2.0.3 | 155 | 6/12/2024 |
2.0.2 | 7,277 | 3/28/2022 |
2.0.1 | 1,950 | 11/6/2021 |
2.0.0 | 477,685 | 5/18/2020 |
1.0.8 | 958 | 5/18/2020 |
1.0.7 | 9,255 | 4/25/2020 |
1.0.6 | 37,770 | 12/2/2019 |
1.0.6-beta | 1,437 | 11/28/2019 |
1.0.5 | 1,935 | 11/17/2019 |
1.0.4 | 871 | 11/17/2019 |
1.0.3 | 930 | 11/13/2019 |
1.0.2 | 984 | 11/11/2019 |
1.0.1 | 1,866 | 11/2/2019 |
1.0.0 | 1,846 | 11/1/2019 |
0.99.4 | 2,624 | 10/30/2019 |
0.99.3 | 981 | 10/30/2019 |
0.99.1 | 946 | 10/29/2019 |
0.99.0 | 951 | 10/29/2019 |
0.0.1 | 986 | 10/28/2019 |