This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal sealed class UriComparer : IEqualityComparer<Uri> { | |
private readonly IEqualityComparer<KeyValuePair<string, StringValues>> _queryComparer; | |
public UriComparer(IEqualityComparer<KeyValuePair<string, StringValues>>? queryComparer = null) { | |
_queryComparer = queryComparer ?? EqualityComparer<KeyValuePair<string, StringValues>>.Default; | |
} | |
public bool Equals(Uri? x, Uri? y) { | |
if (x == y) { return true; } | |
if (x is null || y is null) { return false; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CancellationToken ct = new CancellationTokenSource(0).Token; | |
Task task1 = Task.Run(() => throw new OperationCanceledException(ct)); | |
Task task2 = Task.Run(() => ct.ThrowIfCancellationRequested()); | |
Task.WhenAll(task1, task2).ContinueWith(_ => { | |
task1.Status.Dump(); // Canceled | |
task2.Status.Dump(); // Faulted | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class SpanSplitExtensions { | |
public static int Split<T>(this ReadOnlySpan<T> source, Span<Range> destination, T separator) where T: IEquatable<T> { | |
return Split(source, destination, new ReadOnlySpan<T>(separator)); | |
} | |
public static int Split<T>(this ReadOnlySpan<T> source, Span<Range> destination, ReadOnlySpan<T> separator) where T: IEquatable<T> { | |
int rangesWritten = 0; | |
int offset = 0; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ObjectInvokeExtensions { | |
public static TResult Invoke<T, TResult>(this T value, Func<T, TResult> func) { | |
if (func is null) { throw new ArgumentNullException(nameof(func)); } | |
return func(value); | |
} | |
public static void Invoke<T>(this T value, Action<T> action) { | |
if (action is null) { throw new ArgumentNullException(nameof(action)); } | |
action(value); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TaskCompletionSource<object?> tcs = new( | |
// NOTE: RunContinuationsAsynchronously を付けるとデッドロックしない(非同期に継続される) | |
// TaskCreationOptions.RunContinuationsAsynchronously | |
); | |
ManualResetEventSlim mre = new(); | |
_ = Task.Run(() => { | |
Console.WriteLine("Start background"); | |
tcs.TrySetResult(null); // 2 | |
mre.Set(); // (4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading.Channels; | |
namespace Commons; | |
public interface ITypedLogger<T> { | |
void Log(T log); | |
} | |
public abstract class TypedLogger<T> : ITypedLogger<T>, IDisposable, IAsyncDisposable { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// 定期的に自動更新される値を表すクラス。 | |
/// </summary> | |
public sealed class Later<T> : IDisposable { | |
private readonly CancellationTokenSource _disposingCts = new(); | |
private readonly CancellationTokenSource _stoppingCts; | |
private Task<T> _valueTask; | |
public Later(Func<CancellationToken, Task<T>> factory, TimeSpan period, CancellationToken stoppingToken = default) | |
: this(factory, period, LaterErrorHandling.Capture, stoppingToken) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class DistributedCacheExtensions { | |
public static async Task<T> GetOrSetAsync<T>(this IDistributedCache cache | |
, string key | |
, Func<byte[], T> deserialize | |
, Func<Task<(T, byte[], DistributedCacheEntryOptions options)>> factory | |
, CancellationToken token = default | |
) { | |
if (cache is null) { throw new ArgumentNullException(nameof(cache)); } | |
if (key is null) { throw new ArgumentNullException(nameof(key)); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.Hosting; | |
namespace Commons { | |
/// <summary> | |
/// <see cref="BackgroundService.ExecuteAsync(CancellationToken)"/> で生じた例外が全て Host でハンドルされるよう対応した <see cref="BackgroundService"/> 。 | |
/// </summary> | |
/// <remarks> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TtlLazy<T> { | |
private readonly Func<T> _factory; | |
private readonly TimeSpan _ttl; | |
private T _value = default!; | |
private bool _initialized; | |
private object? _lock; | |
public TtlLazy(Func<T> factory, TimeSpan ttl) { | |
_factory = factory ?? throw new ArgumentNullException(nameof(factory)); |
NewerOlder