コード例 #1
0
        public virtual void RpcTimeout()
        {
            RpcFactory anRpcFactory = new RpcFactory(mySerializer);

            anRpcFactory.RpcTimeout = TimeSpan.FromSeconds(1);

            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));


                IHello aServiceProxy = anRpcClient.Proxy;
                Assert.Throws <TimeoutException>(() => aServiceProxy.Timeout());
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #2
0
        public void RpcCallError()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));


                IHello aServiceProxy = anRpcClient.Proxy;
                Assert.Throws <RpcException>(() => aServiceProxy.Fail());
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #3
0
        public void DynamicRpcCall()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));


                int k = (int)anRpcClient.CallRemoteMethod("Sum", 1, 2);

                Assert.AreEqual(3, k);
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #4
0
        public void RpcCall_NullArgument()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));


                IHello aServiceProxy = anRpcClient.Proxy;
                string k             = aServiceProxy.CreateString(null);

                Assert.AreEqual(null, k);
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #5
0
        public void SubscribeBeforeAttachOutputChannel()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                IHello aServiceProxy = anRpcClient.Proxy;

                AutoResetEvent aClientConnected = new AutoResetEvent(false);
                anRpcClient.ConnectionOpened += (x, y) =>
                {
                    aClientConnected.Set();
                };

                AutoResetEvent             anEventReceived = new AutoResetEvent(false);
                Action <object, EventArgs> anEventHandler  = (x, y) =>
                {
                    anEventReceived.Set();
                };

                // Subscribe before the connection is open.
                aServiceProxy.Close += anEventHandler.Invoke;

                // Open the connection.
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                // Wait until the client is connected.
                aClientConnected.WaitOne();

                // Raise the event in the service.
                aService.RaiseClose();

                Assert.IsTrue(anEventReceived.WaitOne());

                // Unsubscribe.
                aServiceProxy.Close -= anEventHandler.Invoke;

                // Try to raise again.
                aService.RaiseClose();

                Assert.IsFalse(anEventReceived.WaitOne(1000));
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #6
0
        public void PerClientInstanceService()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreatePerClientInstanceService <IHello>(() => new HelloService());

            IRpcClient <IHello> anRpcClient1 = anRpcFactory.CreateClient <IHello>();
            IRpcClient <IHello> anRpcClient2 = anRpcFactory.CreateClient <IHello>();

            try
            {
                ManualResetEvent aClient2Connected = new ManualResetEvent(false);

                string aService1IdFromEvent = null;
                anRpcClient1.Proxy.Open += (x, y) =>
                {
                    aService1IdFromEvent = y.InstanceId;
                };

                string aService2IdFromEvent = null;
                anRpcClient2.Proxy.Open += (x, y) =>
                {
                    aService2IdFromEvent = y.InstanceId;
                    aClient2Connected.Set();
                };

                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient1.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));
                anRpcClient2.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                aClient2Connected.WaitOne(1000);

                string aServiceId1 = anRpcClient1.Proxy.GetInstanceId();
                string aServiceId2 = anRpcClient2.Proxy.GetInstanceId();

                Assert.IsFalse(string.IsNullOrEmpty(aServiceId1));
                Assert.IsFalse(string.IsNullOrEmpty(aService1IdFromEvent));
                Assert.IsFalse(string.IsNullOrEmpty(aServiceId2));
                Assert.IsFalse(string.IsNullOrEmpty(aService2IdFromEvent));
                Assert.AreEqual(aServiceId1, aService1IdFromEvent);
                Assert.AreEqual(aServiceId2, aService2IdFromEvent);
                Assert.AreNotEqual(aServiceId1, aServiceId2);
            }
            finally
            {
                if (anRpcClient1.IsDuplexOutputChannelAttached)
                {
                    anRpcClient1.DetachDuplexOutputChannel();
                }
                if (anRpcClient2.IsDuplexOutputChannelAttached)
                {
                    anRpcClient2.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #7
0
        public void RpcNonGenericEvent_10000()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                IHello aServiceProxy = anRpcClient.Proxy;

                int                        aCounter        = 0;
                AutoResetEvent             anEventReceived = new AutoResetEvent(false);
                Action <object, EventArgs> anEventHandler  = (x, y) =>
                {
                    ++aCounter;
                    if (aCounter == 10000)
                    {
                        anEventReceived.Set();
                    }
                };

                // Subscribe.
                aServiceProxy.Close += anEventHandler.Invoke;

                Stopwatch aStopWatch = new Stopwatch();
                aStopWatch.Start();

                // Raise the event in the service.
                for (int i = 0; i < 10000; ++i)
                {
                    aService.RaiseClose();
                }

                Assert.IsTrue(anEventReceived.WaitOne());

                aStopWatch.Stop();
                Console.WriteLine("Remote event. Elapsed time = " + aStopWatch.Elapsed);

                // Unsubscribe.
                aServiceProxy.Close -= anEventHandler.Invoke;
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #8
0
        public void RpcCall_10000()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                IHello aServiceProxy = anRpcClient.Proxy;

                Stopwatch aStopWatch = new Stopwatch();
                aStopWatch.Start();

                //EneterTrace.StartProfiler();

                for (int i = 0; i < 10000; ++i)
                {
                    aServiceProxy.Sum(1, 2);
                }

                //EneterTrace.StopProfiler();

                aStopWatch.Stop();
                Console.WriteLine("Rpc call. Elapsed time = " + aStopWatch.Elapsed);


                HelloService aService = new HelloService();

                Stopwatch aStopWatch2 = new Stopwatch();
                aStopWatch2.Start();

                for (int i = 0; i < 10000; ++i)
                {
                    aService.Sum(1, 2);
                }

                aStopWatch2.Stop();
                Console.WriteLine("Local call. Elapsed time = " + aStopWatch2.Elapsed);
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #9
0
        public void DynamicRpcGenericEvent()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                AutoResetEvent          anEventReceived = new AutoResetEvent(false);
                string                  aReceivedEvent  = "";
                EventHandler <OpenArgs> anEventHandler  = (x, y) =>
                {
                    aReceivedEvent = y.Name;
                    anEventReceived.Set();
                };

                // Subscribe.
                anRpcClient.SubscribeRemoteEvent("Open", anEventHandler);

                // Raise the event in the service.
                OpenArgs anOpenArgs = new OpenArgs()
                {
                    Name = "Hello"
                };
                aService.RaiseOpen(anOpenArgs);

                Assert.IsTrue(anEventReceived.WaitOne());
                Assert.AreEqual("Hello", aReceivedEvent);

                // Unsubscribe.
                anRpcClient.UnsubscribeRemoteEvent("Open", anEventHandler);

                // Try to raise again.
                aService.RaiseOpen(anOpenArgs);

                Assert.IsFalse(anEventReceived.WaitOne(1000));
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #10
0
        public void RpcGenericEvent()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                IHello aServiceProxy = anRpcClient.Proxy;

                AutoResetEvent            anEventReceived = new AutoResetEvent(false);
                Action <object, OpenArgs> anEventHandler  = (x, y) =>
                {
                    anEventReceived.Set();
                };

                // Subscribe.
                aServiceProxy.Open += anEventHandler.Invoke;

                // Raise the event in the service.
                OpenArgs anOpenArgs = new OpenArgs()
                {
                    Name = "Hello"
                };
                aService.RaiseOpen(anOpenArgs);

                Assert.IsTrue(anEventReceived.WaitOne());

                // Unsubscribe.
                aServiceProxy.Open -= anEventHandler.Invoke;

                // Try to raise again.
                aService.RaiseOpen(anOpenArgs);

                Assert.IsFalse(anEventReceived.WaitOne(1000));
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #11
0
 private void stopRPC_Click(object sender, EventArgs e)
 {
     if (aService.IsDuplexInputChannelAttached == true)
     {
         Console.WriteLine("Duplex Input channel was attached");
     }
     aService.DetachDuplexInputChannel();
     //if (!aService.IsDuplexInputChannelAttached == true)
     //{
     Console.WriteLine("Service Ended");
     // }
 }
コード例 #12
0
        public void DynamicRpcNonGenericEvent()
        {
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);
            IRpcClient <IHello>  anRpcClient  = anRpcFactory.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));

                AutoResetEvent           anEventReceived = new AutoResetEvent(false);
                EventHandler <EventArgs> anEventHandler  = (x, y) =>
                {
                    anEventReceived.Set();
                };

                // Subscribe.
                anRpcClient.SubscribeRemoteEvent <EventArgs>("Close", anEventHandler);

                // Raise the event in the service.
                aService.RaiseClose();

                Assert.IsTrue(anEventReceived.WaitOne());

                // Unsubscribe.
                anRpcClient.UnsubscribeRemoteEvent("Close", anEventHandler);

                // Try to raise again.
                aService.RaiseClose();

                Assert.IsFalse(anEventReceived.WaitOne(1000));
            }
            finally
            {
                if (anRpcClient.IsDuplexOutputChannelAttached)
                {
                    anRpcClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #13
0
ファイル: TalkFlow.cs プロジェクト: neemesis/EneterTest
        public TalkFlow()
        {
            var talk = new Talk();

            IRpcFactory         factory = new RpcFactory();
            IRpcService <ITalk> service = factory.CreateSingleInstanceService <ITalk>(talk);

            IMessagingSystemFactory messaging    = new TcpMessagingSystemFactory();
            IDuplexInputChannel     inputChannel = messaging.CreateDuplexInputChannel("tcp://127.0.0.1:8045/");

            service.AttachDuplexInputChannel(inputChannel);

            Console.WriteLine("Service started. Press ENTER to stop.");
            Console.ReadLine();

            service.DetachDuplexInputChannel();
        }
コード例 #14
0
        public void MultipleClients_RemoteEvent_10()
        {
            //EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;
            //EneterTrace.StartProfiler();

            HelloService         aService     = new HelloService();
            RpcFactory           anRpcFactory = new RpcFactory(mySerializer);
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(aService);

            IRpcClient <IHello>[] aClients = new IRpcClient <IHello> [10];
            for (int i = 0; i < aClients.Length; ++i)
            {
                aClients[i] = anRpcFactory.CreateClient <IHello>();
            }

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));

                // Clients open connection.
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    aClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));
                }

                // Subscribe to remote event from the service.
                AutoResetEvent anOpenReceived           = new AutoResetEvent(false);
                AutoResetEvent aCloseReceived           = new AutoResetEvent(false);
                AutoResetEvent anAllCleintsSubscribed   = new AutoResetEvent(false);
                int            anOpenCounter            = 0;
                int            aCloseCounter            = 0;
                int            aSubscribedClientCounter = 0;
                object         aCounterLock             = new object();
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    IRpcClient <IHello> aClientTmp = aClient;
                    ThreadPool.QueueUserWorkItem(xx =>
                    {
                        aClientTmp.Proxy.Open += (x, y) =>
                        {
                            lock (aCounterLock)
                            {
                                ++anOpenCounter;
                                if (anOpenCounter == aClients.Length)
                                {
                                    anOpenReceived.Set();
                                }
                            }
                        };

                        aClientTmp.Proxy.Close += (x, y) =>
                        {
                            lock (aCounterLock)
                            {
                                ++aCloseCounter;
                                if (aCloseCounter == aClients.Length)
                                {
                                    aCloseReceived.Set();
                                }
                            }
                        };

                        lock (aCounterLock)
                        {
                            ++aSubscribedClientCounter;
                            if (aSubscribedClientCounter == aClients.Length)
                            {
                                anAllCleintsSubscribed.Set();
                            }
                        }

                        Thread.Sleep(1);
                    });
                }

                // Wait until all clients are subscribed.
                anAllCleintsSubscribed.WaitOne();

                // Servicde raises two different events.
                OpenArgs anOpenArgs = new OpenArgs()
                {
                    Name = "Hello"
                };
                aService.RaiseOpen(anOpenArgs);
                aService.RaiseClose();


                anOpenReceived.WaitOne();
                aCloseReceived.WaitOne();
            }
            finally
            {
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    aClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #15
0
        public void MultipleClients_RemoteCall_10()
        {
            //EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;
            //EneterTrace.StartProfiler();

            RpcFactory anRpcFactory = new RpcFactory(mySerializer)
            {
                RpcTimeout = TimeSpan.FromSeconds(30)
            };
            IRpcService <IHello> anRpcService = anRpcFactory.CreateSingleInstanceService <IHello>(new HelloService());

            IRpcClient <IHello>[] aClients = new IRpcClient <IHello> [10];
            for (int i = 0; i < aClients.Length; ++i)
            {
                aClients[i] = anRpcFactory.CreateClient <IHello>();
            }

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));

                // Clients open connection.
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    aClient.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId));
                }

                // Clients communicate with the service in parallel.
                AutoResetEvent aDone        = new AutoResetEvent(false);
                int            aCounter     = 0;
                object         aCounterLock = new object();
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    ThreadPool.QueueUserWorkItem(x =>
                    {
                        try
                        {
                            aClient.Proxy.Sum(10, 20);

                            lock (aCounterLock)
                            {
                                ++aCounter;
                                if (aCounter == aClients.Length)
                                {
                                    aDone.Set();
                                }
                            }
                            Thread.Sleep(1);
                        }
                        catch (Exception err)
                        {
                            EneterTrace.Error("Detected Exception.", err);
                            aDone.Set();
                        }
                    });
                }

                aDone.WaitOne();

                //EneterTrace.StopProfiler();

                Assert.AreEqual(aClients.Length, aCounter);
            }
            finally
            {
                foreach (IRpcClient <IHello> aClient in aClients)
                {
                    aClient.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }
コード例 #16
0
        public void RpcGenericEvent_SerializerPerClient()
        {
            string aFirstClientId = null;

            RpcFactory anRpcClientFactory1 = new RpcFactory(new XmlStringSerializer());
            RpcFactory anRpcClientFactory2 = new RpcFactory(new BinarySerializer());
            RpcFactory anRpcServiceFactory = new RpcFactory()
            {
                SerializerProvider = x => (x == aFirstClientId) ? (ISerializer) new XmlStringSerializer() : (ISerializer) new BinarySerializer()
            };

            HelloService         aService     = new HelloService();
            IRpcService <IHello> anRpcService = anRpcServiceFactory.CreateSingleInstanceService <IHello>(aService);

            anRpcService.ResponseReceiverConnected += (x, y) => aFirstClientId = aFirstClientId ?? y.ResponseReceiverId;

            IRpcClient <IHello> anRpcClient1 = anRpcClientFactory1.CreateClient <IHello>();
            IRpcClient <IHello> anRpcClient2 = anRpcClientFactory2.CreateClient <IHello>();

            try
            {
                anRpcService.AttachDuplexInputChannel(myMessaging.CreateDuplexInputChannel(myChannelId));
                anRpcClient1.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId, "Client1"));
                anRpcClient2.AttachDuplexOutputChannel(myMessaging.CreateDuplexOutputChannel(myChannelId, "Client2"));

                AutoResetEvent            anEvent1Received = new AutoResetEvent(false);
                Action <object, OpenArgs> anEventHandler1  = (x, y) =>
                {
                    anEvent1Received.Set();
                };

                AutoResetEvent            anEvent2Received = new AutoResetEvent(false);
                Action <object, OpenArgs> anEventHandler2  = (x, y) =>
                {
                    anEvent2Received.Set();
                };

                // Subscribe.
                anRpcClient1.Proxy.Open += anEventHandler1.Invoke;
                anRpcClient2.Proxy.Open += anEventHandler2.Invoke;

                // Raise the event in the service.
                OpenArgs anOpenArgs = new OpenArgs()
                {
                    Name = "Hello"
                };
                aService.RaiseOpen(anOpenArgs);

                anEvent1Received.WaitIfNotDebugging(1000);
                anEvent2Received.WaitIfNotDebugging(1000);

                // Unsubscribe.
                anRpcClient1.Proxy.Open -= anEventHandler1.Invoke;
                anRpcClient2.Proxy.Open -= anEventHandler2.Invoke;

                // Try to raise again.
                aService.RaiseOpen(anOpenArgs);

                Assert.IsFalse(anEvent1Received.WaitOne(1000));
                Assert.IsFalse(anEvent2Received.WaitOne(1000));
            }
            finally
            {
                if (anRpcClient1.IsDuplexOutputChannelAttached)
                {
                    anRpcClient1.DetachDuplexOutputChannel();
                }

                if (anRpcClient2.IsDuplexOutputChannelAttached)
                {
                    anRpcClient2.DetachDuplexOutputChannel();
                }

                if (anRpcService.IsDuplexInputChannelAttached)
                {
                    anRpcService.DetachDuplexInputChannel();
                }
            }
        }