예제 #1
0
 public void MultiThreadIsSafe()
 {
     using (var cts = new CancellationTokenSource(Utils.TestTimeoutMs))
     {
         var delayedException = new Utils.DelayedException();
         using (var svc1 = MakeAgent(1))
             using (var svc2 = MakeAgent(2))
             {
                 for (int i = 0; i < 1000; ++i)
                 {
                     {
                         var category = "DisposeInHandler" + i;
                         svc1.PublishAsync(category, "");
                         svc2.PublishAsync(category, "");
                         IDiscoverySubscription sub = svc2.Subscribe(category);
                         sub.Updated +=
                             delayedException.Wrap <IDiscoverySubscription>(
                                 subscription =>
                         {
                             Assert.True(subscription.Resources.Count() >= 0);
                             subscription.Dispose();
                         });
                     }
                     {
                         var category = "DisposeInOtherThread" + i;
                         svc1.PublishAsync(category, "");
                         svc2.PublishAsync(category, "");
                         IDiscoverySubscription sub = svc2.Subscribe(category);
                         Task.Delay(random_.Next(0, 200)).ContinueWith(
                             delayedException.Wrap <Task>(
                                 _ =>
                         {
                             Assert.True(sub.Resources.Count() >= 0);
                             sub.Dispose();
                         }));
                     }
                 }
             }
         Thread.Sleep(200);
         delayedException.Rethrow();
     }
 }
예제 #2
0
        public void CanDisposeSubscriptions()
        {
            const string           category1 = "CanDisposeSubscriptions1";
            const string           category2 = "CanDisposeSubscriptions2";
            IDiscoverySubscription surviving;
            IDiscoverySubscription survivingInHandler;

            var handlerEntered = new ManualResetEvent(false);
            var agentDisposed  = new ManualResetEvent(false);

            var delayedException = new Utils.DelayedException();

            using (var cts = new CancellationTokenSource(Utils.TestTimeoutMs))
                using (var publishingAgent = MakeAgent(1))
                {
                    publishingAgent.PublishAsync(category1, "", null, cts.Token).Wait();
                    publishingAgent.PublishAsync(category2, "", null, cts.Token).Wait();
                    var agent = MakeAgent(2);

                    {
                        bool subIsDisposed    = false;
                        var  subDisposedEvent = new ManualResetEvent(false);
                        agent.Subscribe(category1).Updated +=
                            delayedException.Wrap <IDiscoverySubscription>(
                                sub =>
                        {
                            // Tests for https://github.com/microsoft/MixedReality-Sharing/issues/83.
                            if (sub.Resources.Any())
                            {
                                // Dispose the task from its handler.
                                sub.Dispose();
                                // The handler is not called after disposal.
                                Assert.False(subIsDisposed);
                                subIsDisposed = true;
                                subDisposedEvent.Set();
                            }
                        });
                        // Wait until the subscription is disposed before going on.
                        WaitWithCancellation(subDisposedEvent, cts.Token);
                    }

                    var survivingDisposedEvent = new ManualResetEvent(false);
                    surviving = agent.Subscribe(category1);

                    {
                        bool subIsDisposed = false;
                        survivingInHandler          = agent.Subscribe(category2);
                        survivingInHandler.Updated +=
                            delayedException.Wrap <IDiscoverySubscription>(
                                sub =>
                        {
                            handlerEntered.Set();

                            // Wait until the agent is disposed by the main thread.
                            WaitWithCancellation(agentDisposed, cts.Token);

                            // Dispose the task from its handler.
                            sub.Dispose();
                            // The handler is not called after disposal.
                            Assert.False(subIsDisposed);
                            subIsDisposed = true;
                            survivingDisposedEvent.Set();
                        });
                    }

                    // Wait until the handler is entered.
                    WaitWithCancellation(handlerEntered, cts.Token);

                    // Dispose the agent while in the handler.
                    agent.Dispose();

                    // Signal the handler to go ahead and dispose the subscription.
                    agentDisposed.Set();

                    // The resources in the other surviving subscription are cleared eventually.
                    while (surviving.Resources.Any())
                    {
                        Task.Delay(1).Wait(cts.Token);
                    }

                    // Dispose the other surviving subscription.
                    surviving.Dispose();

                    WaitWithCancellation(survivingDisposedEvent, cts.Token);

                    delayedException.Rethrow();
                }
        }