mirror of
https://github.com/scratchfoundation/scratch-link.git
synced 2025-07-13 14:03:56 -04:00
We really use the socket state to control the session, so there's no need to also pass a CancellationToken around. The exception was being caused when an unlucky callback happened after a session was disposed and the callback tried to get a new token to check cancellation. If the token source is already disposed, it can't provide a new token. Also, remove some excessive logging and add more exception logging.
83 lines
3.6 KiB
C#
83 lines
3.6 KiB
C#
// <copyright file="SemaphoreSlimExtensions.cs" company="Scratch Foundation">
|
|
// Copyright (c) Scratch Foundation. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace ScratchLink.Extensions;
|
|
|
|
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
/// <summary>
|
|
/// Extensions for <see cref="SemaphoreSlim"/>.
|
|
/// </summary>
|
|
public static class SemaphoreSlimExtensions
|
|
{
|
|
/// <summary>
|
|
/// Like <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>, but generates a <see cref="DisposableSemaphoreLock"/> which will release the semaphore on <see cref="DisposableSemaphoreLock.Dispose"/>.
|
|
/// </summary>
|
|
/// <param name="semaphore">The semaphore on which to call <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>.</param>
|
|
/// <param name="cancellationToken"><inheritdoc cref="SemaphoreSlim.WaitAsync(CancellationToken)"/></param>
|
|
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
|
|
public static async Task<IDisposable> WaitDisposableAsync(
|
|
this SemaphoreSlim semaphore,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var disposableLock = new DisposableSemaphoreLock(semaphore);
|
|
await semaphore.WaitAsync(cancellationToken);
|
|
return disposableLock;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Like <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>, but generates a <see cref="DisposableSemaphoreLock"/> which will release the semaphore on <see cref="DisposableSemaphoreLock.Dispose"/>.
|
|
/// </summary>
|
|
/// <param name="semaphore">The semaphore on which to call <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>.</param>
|
|
/// <param name="timeout"><inheritdoc cref="SemaphoreSlim.WaitAsync(TimeSpan)"/></param>
|
|
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
|
|
public static async Task<IDisposable> WaitDisposableAsync(
|
|
this SemaphoreSlim semaphore,
|
|
TimeSpan timeout)
|
|
{
|
|
var disposableLock = new DisposableSemaphoreLock(semaphore);
|
|
await semaphore.WaitAsync(timeout);
|
|
return disposableLock;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Like <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>, but generates a <see cref="DisposableSemaphoreLock"/> which will release the semaphore on <see cref="DisposableSemaphoreLock.Dispose"/>.
|
|
/// </summary>
|
|
/// <param name="semaphore">The semaphore on which to call <see cref="SemaphoreSlim.WaitAsync(CancellationToken)"/>.</param>
|
|
/// <param name="timeout"><inheritdoc cref="SemaphoreSlim.WaitAsync(TimeSpan)"/></param>
|
|
/// <param name="cancellationToken"><inheritdoc cref="SemaphoreSlim.WaitAsync(CancellationToken)"/></param>
|
|
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
|
|
public static async Task<IDisposable> WaitDisposableAsync(
|
|
this SemaphoreSlim semaphore,
|
|
TimeSpan timeout,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var disposableLock = new DisposableSemaphoreLock(semaphore);
|
|
await semaphore.WaitAsync(timeout, cancellationToken);
|
|
return disposableLock;
|
|
}
|
|
|
|
private class DisposableSemaphoreLock : IDisposable
|
|
{
|
|
private SemaphoreSlim semaphore;
|
|
|
|
public DisposableSemaphoreLock(SemaphoreSlim semaphore)
|
|
{
|
|
this.semaphore = semaphore;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (this.semaphore == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.semaphore.Release();
|
|
this.semaphore = null;
|
|
}
|
|
}
|
|
}
|