/// <summary> /// Creates a disposable object that will lock the Queue for the duration of an event, disallowing any new tasks to be run beneath it. /// TODO: Is it enough to just use ExclusionLocker and be done with it? Probably. /// </summary> /// <param name="pipe"></param> /// <returns></returns> public static IDisposable BeginExclusiveOperation(this IEventPipe pipe) { //Prevent deadlock because we are already running exclusively. if (TaskScheduler.Current.Id == pipe.ExclusiveScheduler.Id) { return(Disposable.Empty); } void runShim(object state) { var casthadle = (Tuple <ManualResetEventSlim, CancellationToken>)state; casthadle.Item1.Set(); casthadle.Item2.WaitHandle.WaitOne(); } var src = new CancellationTokenSource(); ManualResetEventSlim oneSlim = new ManualResetEventSlim(); Tuple <ManualResetEventSlim, CancellationToken> thing = new Tuple <ManualResetEventSlim, CancellationToken>(oneSlim, src.Token); Task.Run(() => new Task(runShim, thing).RunSynchronously(pipe.ExclusiveScheduler), pipe.MainToken); //pipe.ExclusionLocker.Wait(()=> new TaskFactory(pipe.ExclusiveScheduler).StartNew(() => //{ // oneSlim.Set(); // src.Token.WaitHandle.WaitOne(); //})); oneSlim.Wait(pipe.MainToken); return(Disposable.Create(src, s => { s.Cancel(false); s.Dispose(); })); }
public EventPipeTests(ITestOutputHelper output) { outp = output; pipe = new EventPipe(); var provCol = new ServiceCollection(); provCol.AddScoped <List <int> >(); testProv = provCol.BuildServiceProvider(); }
public async void AsyncDisposeTest() { pipe = new EventPipe(); var endThing = new TaskCompletionSource <bool>(); var disposer = new RefCountDisposable(Disposable.Create(() => endThing.SetResult(true))); for (var i = 0; i < 100; i++) { pipe.ObserveFirst.Subscribe(new TestObserver(i, outp, "first", disposer.GetDisposable())); pipe.ObserveConcurrent.Subscribe(new TestObserver(i, outp, "reader", disposer.GetDisposable())); pipe.ObserveSynchronous.Subscribe(new TestObserver(i, outp, "writer", disposer.GetDisposable())); } disposer.Dispose(); //var testTask = new List<Task>(); var totalDisposer = new RefCountDisposable(Disposable.Create(() => pipe.Complete())); var rand = new Random(); Parallel.ForEach(Enumerable.Range(0, 99), async x => { using (totalDisposer.GetDisposable()) { using (var scp = testProv.CreateScope()) { var e = new MessageEvent { IgnoreThis = false, Services = scp.ServiceProvider.CreateScope().ServiceProvider, Scenario = VersaCommsID.FromEnum(EVersaCommIDType.Scenario, 0), Player = new UnionType <VersaCommsID, IPlayer>(0), Terminal = new UnionType <VersaCommsID, IVersaWriter>(0), FullMessage = x.ToString(), Entity = new UnionType <VersaCommsID, IEntity>(0), }; await Task.Yield(); await pipe.ProcessEvent(e); } } }); //totalDisposer.Dispose(); //scp.Dispose(); //await Task.WhenAll(testTask); await Task.Delay(200); totalDisposer.Dispose(); //await Task.Delay(200); await endThing.Task; //pipe.Dispose(); }