using System; using System.Linq; using System.Collections.Generic; using System.Collections.Concurrent; using System.Reflection; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; int data = 0, ready = 0, observed = -1; OwnedThreads.Run( () => { data = 37; Volatile.Write(ref ready, 1); }, () => { if (!SpinWait.SpinUntil(() => Volatile.Read(ref ready) == 1, TimeSpan.FromSeconds(5))) throw new TimeoutException(); observed = data; }); Console.WriteLine($"value:{observed}"); Console.WriteLine($"ready:{Volatile.Read(ref ready)}"); public static class OwnedThreads { public static void Run(params Action[] actions) { var errors = new ConcurrentQueue(); var threads = actions.Select(action => new Thread(() => { try { action(); } catch (Exception error) { errors.Enqueue(error); } }) { IsBackground = true }).ToArray(); foreach (var thread in threads) thread.Start(); foreach (var thread in threads) if (!thread.Join(TimeSpan.FromSeconds(8))) throw new TimeoutException("Owned worker did not finish"); if (!errors.IsEmpty) throw new AggregateException(errors); } }