Skip to content

Instantly share code, notes, and snippets.

@Hotrian
Last active October 20, 2022 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hotrian/16b3d00dc3127c5afe24ee2615e82f33 to your computer and use it in GitHub Desktop.
Save Hotrian/16b3d00dc3127c5afe24ee2615e82f33 to your computer and use it in GitHub Desktop.

The code given here is a very simplified example and not for production usage.

The following snippet demonstrates TAP Task Synchronization using SemaphoreSlims in the context of upgrading an existing EAP application which relies on lock statements. This snippet of code doesn't do anything particularly useful, because it isn't supposed to - it is only to demonstrate one way of migrating from the EAP model to the TAP model.

See the blog entry for more information.

namespace Hotrian.com_Tutorials
{
public static class Program
{
public static async void Main()
{
var obj = new SensitiveResource();
// Store the values X = 10, Y = 20 in a single operation
// obj.SetResource(10, 20);
// Retrieve the resource values in a single operation
// var resource = obj.GetResource();
// Console.WriteLine($"X: {resource.Item1}, Y: {resource.Item2}"); // X: 10, Y: 20
// Store the values X = 10, Y = 20 in a single operation
await obj.SetResourceAsync(10, 20);
// Retrieve the resource values in a single operation
var resourceAsync = await obj.GetResourceAsync();
Console.WriteLine($"X: {resourceAsync.Item1}, Y: {resourceAsync.Item2}"); // X: 10, Y: 20
}
}
public class SensitiveResource
{
private readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
private int _x;
private int _y;
// Remap the old EAP stubs to our new TAP methods, so older code can synchronize properly with newer code
/// <inheritdoc cref="GetResourceAsync"/>
public Tuple<int, int> GetResource() => GetResourceAsync().GetAwaiter().GetResult();
/// <inheritdoc cref="SetResourceAsync"/>
public void SetResource(int x, int y) => SetResourceAsync(x, y).GetAwaiter().GetResult();
/// <summary> Gets the Resources stored in a single operation. </summary>
public async Task<Tuple<int, int>> GetResourceAsync()
{
// Wait until the resource handle is available for us to block
await _semaphoreSlim.WaitAsync();
try
{
// Do sensitive operation
return new Tuple<int, int>(_x, _y);
}
finally
{
// Release the resource handle for the next thread
_semaphoreSlim.Release();
}
}
/// <summary> Sets the Resources to <paramref name="x"/> and <paramref name="y"/> in a single operation. </summary>
public async Task SetResourceAsync(int x, int y)
{
// Wait until the resource handle is available for us to block
await _semaphoreSlim.WaitAsync();
try
{
// Do sensitive operation
_x = x;
_y = y;
}
finally
{
// Release the resource handle for the next thread
_semaphoreSlim.Release();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment