Posts

Showing posts from August, 2023

On AsyncLazy in .NET

Today I saw a post on linkedin on combining Lazy<T> with a Task, and then awaiting on lazy.Value, and if developers should ever use such an approach. A few thoughts came to mind about why we should not , for example, inability to pass a cancellation token in a transparent manner and overall obscurity of applying a strictly non-async pattern to an async operation. But then I thought about how would I implement a real async lazy wrapper. Below is what came out. This is just an idea, though it does look quite usable :) public sealed class AsyncLazy<T> : IDisposable where T : class { private const int MaxSpinWaitCount = 10; private enum Stages { Uninitialized = 0, Producing, Produced } private ManualResetEventSlim? resetEvent = new (false, MaxSpinWaitCount); private readonly Func<CancellationToken, Task<T>> producer; private T value; private int stage = (int)Stages.Uninitialized; public AsyncLazy(Func<CancellationToken, Task<T>> produce

On Serilog 'log enrichment' feature

This brief note is for .NET developers who use Serilog (great tool, by the way!) for logging implementations. I want to cover a very powerful, though rarely spoken of, feature - 'log enrichment'. It is an interesting concept and implementation which they describe as 'log events can be enriched with properties in various ways'. The main idea is that whatever log event gets written, it may be improved with custom data coming from various sources. So, what implementing log enrichers would give and how may it be applied? The first thing to mention is that neither business code, nor application code is designed to produce logs; it has a completely different purpose. The less logging code we have inside our business and application code, the cleaner, less coupled, and more cohesive our code is. Those working with enterprise code are quite used to code 'spiced up' with logging statements. While 'what and when' to log and 'what and when' not to log is a