Пример #1
0
        /// <summary>
        /// This method is called to post the status of the node. Because status is used
        /// to report errors and to respond to inactivity notices, we use a separate queue
        /// to deliver status event to the shared memory. Otherwise status maybe be delayed
        /// if it is stuck behind a large number of other events. We also wait for the status
        /// to be sent before returning.
        /// </summary>
        public void PostStatus(int nodeId, NodeStatus nodeStatus, bool blockUntilSent)
        {
            // We should not be on the running on the callback writer thread
            ErrorUtilities.VerifyThrow(Thread.CurrentThread != writerThread, "Should never call this function from the writer thread");

            LocalCallDescriptorForPostStatus callDescriptor =
                new LocalCallDescriptorForPostStatus(nodeStatus);

            nodeHiPriCommandQueue.Enqueue(callDescriptor);

            // We need to block until the event we posted has been processed, but if the writer thread
            // exit due to an error the shared memory is no longer valid so there is no way to send the message
            while (blockUntilSent && !writerThreadHasExited && nodeHiPriCommandQueue.Count > 0)
            {
                nodeHiPriCommandQueue.QueueEmptyEvent.WaitOne(1000, false);

                // Check if the communication threads are supposed to exit
                if (exitCommunicationThreads.WaitOne(0, false))
                {
                    break;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// This method first reads the objectId as an int from the stream,
        /// this int should be found in the "ObjectType" enumeration. This
        /// objectId informs the method what kind of object should be
        /// deserialized and returned from the method. The objectId is an
        /// output parameter. This parameter is also returned so it can be
        /// used in the read and write methods to determine if
        /// a frame or end marker was found.
        /// </summary>
        private object DeserializeFromStream(out int objectId)
        {
            object objectRead = null;

            objectId = readStream.ReadByte();
            switch ((ObjectType)objectId)
            {
            case ObjectType.NetSerialization:
                objectRead = binaryFormatter.Deserialize(readStream);
                break;

            case ObjectType.FrameMarker:
                objectRead = binaryReader.ReadInt32();
                break;

            case ObjectType.PostBuildResult:
                objectRead = new LocalCallDescriptorForPostBuildResult();
                ((LocalCallDescriptorForPostBuildResult)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.PostBuildRequests:
                objectRead = new LocalCallDescriptorForPostBuildRequests();
                ((LocalCallDescriptorForPostBuildRequests)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.PostLoggingMessagesToHost:
                objectRead = new LocalCallDescriptorForPostLoggingMessagesToHost();
                ((LocalCallDescriptorForPostLoggingMessagesToHost)objectRead).CreateFromStream(binaryReader, loggingTypeCache);
                break;

            case ObjectType.InitializeNode:
                objectRead = new LocalCallDescriptorForInitializeNode();
                ((LocalCallDescriptorForInitializeNode)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.InitializationComplete:
                objectRead = new LocalCallDescriptorForInitializationComplete();
                ((LocalCallDescriptorForInitializationComplete)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.UpdateNodeSettings:
                objectRead = new LocalCallDescriptorForUpdateNodeSettings();
                ((LocalCallDescriptorForUpdateNodeSettings)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.RequestStatus:
                objectRead = new LocalCallDescriptorForRequestStatus();
                ((LocalCallDescriptorForRequestStatus)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.PostCacheEntriesToHost:
                objectRead = new LocalCallDescriptorForPostingCacheEntriesToHost();
                ((LocalCallDescriptorForPostingCacheEntriesToHost)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.GetCacheEntriesFromHost:
                objectRead = new LocalCallDescriptorForGettingCacheEntriesFromHost();
                ((LocalCallDescriptorForGettingCacheEntriesFromHost)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.ShutdownComplete:
                objectRead = new LocalCallDescriptorForShutdownComplete();
                ((LocalCallDescriptorForShutdownComplete)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.ShutdownNode:
                objectRead = new LocalCallDescriptorForShutdownNode();
                ((LocalCallDescriptorForShutdownNode)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.PostIntrospectorCommand:
                objectRead = new LocalCallDescriptorForPostIntrospectorCommand(null, null);
                ((LocalCallDescriptorForPostIntrospectorCommand)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.GenericSingleObjectReply:
                objectRead = new LocalReplyCallDescriptor();
                ((LocalReplyCallDescriptor)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.PostStatus:
                objectRead = new LocalCallDescriptorForPostStatus();
                ((LocalCallDescriptorForPostStatus)objectRead).CreateFromStream(binaryReader);
                break;

            case ObjectType.EndMarker:
                return(null);

            default:
                ErrorUtilities.VerifyThrow(false, "Should not be here, ObjectId:" + objectId + "Next:" + readStream.ReadByte());
                break;
            }
            return(objectRead);
        }
Пример #3
0
 /// <summary>
 /// This method first reads the objectId as an int from the stream, 
 /// this int should be found in the "ObjectType" enumeration. This 
 /// objectId informs the method what kind of object should be 
 /// deserialized and returned from the method. The objectId is an
 /// output parameter. This parameter is also returned so it can be 
 /// used in the read and write methods to determine if 
 /// a frame or end marker was found.
 /// </summary>
 private object DeserializeFromStream(out int objectId)
 {
     object objectRead = null;
     objectId = readStream.ReadByte();
     switch ((ObjectType)objectId)
     {
         case ObjectType.NetSerialization:
             objectRead = binaryFormatter.Deserialize(readStream);
             break;
         case ObjectType.FrameMarker:
             objectRead = binaryReader.ReadInt32();
             break;
         case ObjectType.PostBuildResult:
             objectRead = new LocalCallDescriptorForPostBuildResult();
             ((LocalCallDescriptorForPostBuildResult)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.PostBuildRequests:
             objectRead = new LocalCallDescriptorForPostBuildRequests();
             ((LocalCallDescriptorForPostBuildRequests)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.PostLoggingMessagesToHost:
             objectRead = new LocalCallDescriptorForPostLoggingMessagesToHost();
             ((LocalCallDescriptorForPostLoggingMessagesToHost)objectRead).CreateFromStream(binaryReader, loggingTypeCache);
             break;
         case ObjectType.InitializeNode:
             objectRead = new LocalCallDescriptorForInitializeNode();
             ((LocalCallDescriptorForInitializeNode)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.InitializationComplete:
             objectRead = new LocalCallDescriptorForInitializationComplete();
             ((LocalCallDescriptorForInitializationComplete)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.UpdateNodeSettings:
             objectRead = new LocalCallDescriptorForUpdateNodeSettings();
             ((LocalCallDescriptorForUpdateNodeSettings)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.RequestStatus:
             objectRead = new LocalCallDescriptorForRequestStatus();
             ((LocalCallDescriptorForRequestStatus)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.PostCacheEntriesToHost:
             objectRead = new LocalCallDescriptorForPostingCacheEntriesToHost();
             ((LocalCallDescriptorForPostingCacheEntriesToHost)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.GetCacheEntriesFromHost:
             objectRead = new LocalCallDescriptorForGettingCacheEntriesFromHost();
             ((LocalCallDescriptorForGettingCacheEntriesFromHost)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.ShutdownComplete:
             objectRead = new LocalCallDescriptorForShutdownComplete();
             ((LocalCallDescriptorForShutdownComplete)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.ShutdownNode:
             objectRead = new LocalCallDescriptorForShutdownNode();
             ((LocalCallDescriptorForShutdownNode)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.PostIntrospectorCommand:
             objectRead = new LocalCallDescriptorForPostIntrospectorCommand(null, null);
             ((LocalCallDescriptorForPostIntrospectorCommand)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.GenericSingleObjectReply:
             objectRead = new LocalReplyCallDescriptor();
             ((LocalReplyCallDescriptor)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.PostStatus:
             objectRead = new LocalCallDescriptorForPostStatus();
             ((LocalCallDescriptorForPostStatus)objectRead).CreateFromStream(binaryReader);
             break;
         case ObjectType.EndMarker:
             return null;
         default:
             ErrorUtilities.VerifyThrow(false, "Should not be here, ObjectId:" + objectId + "Next:" + readStream.ReadByte());
             break;
     }
     return objectRead;
 }
Пример #4
0
 private static void VerifyNodeStatus1(LocalCallDescriptorForPostStatus nodeStatus1CallDescriptor)
 {
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.IsActive);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.IsLaunchInProgress);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.LastLoopActivity == 4);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.LastTaskActivity == 3);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.QueueDepth == 2);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.RequestId == 1);
     Assert.IsTrue(nodeStatus1CallDescriptor.StatusOfNode.UnhandledException == null);
 }
Пример #5
0
 private static void VerifyNodeStatus2(LocalCallDescriptorForPostStatus nodeStatus2CallDescriptor)
 {
     Assert.IsTrue(nodeStatus2CallDescriptor.StatusOfNode.IsActive);
     Assert.IsFalse(nodeStatus2CallDescriptor.StatusOfNode.IsLaunchInProgress);
     Assert.IsTrue(nodeStatus2CallDescriptor.StatusOfNode.QueueDepth == 0);
     Assert.IsTrue(nodeStatus2CallDescriptor.StatusOfNode.RequestId == -1);
     Assert.IsTrue(string.Compare(nodeStatus2CallDescriptor.StatusOfNode.UnhandledException.Message, "I am bad", StringComparison.OrdinalIgnoreCase) == 0);
 }
Пример #6
0
        public void TestHiPrioritySend()
        {
            string name = Guid.NewGuid().ToString();
            // Create the shared memory buffer
            SharedMemory readSharedMemory =
                  new SharedMemory
                  (
                        name,
                        SharedMemoryType.ReadOnly,
                        true
                  );


            SharedMemory writeSharedMemory =
                new SharedMemory
                (
                    name,
                    SharedMemoryType.WriteOnly,
                    true
                );

            DualQueue<LocalCallDescriptor> queue = new DualQueue<LocalCallDescriptor>();
            DualQueue<LocalCallDescriptor> hiPriQueue = new DualQueue<LocalCallDescriptor>();


            int numberOfEvents = 20;
            LocalCallDescriptorForPostLoggingMessagesToHost LargeLogEvent = CreatePostMessageCallDescriptor(numberOfEvents);
            queue.Enqueue(LargeLogEvent);
            LocalCallDescriptorForPostStatus nodeStatusExcept = new LocalCallDescriptorForPostStatus(new NodeStatus(new Exception("I am bad")));
            hiPriQueue.Enqueue(nodeStatusExcept);

            writeSharedMemory.Write(queue, hiPriQueue, true);
            IList localCallDescriptorList = readSharedMemory.Read();

            Assert.IsTrue(localCallDescriptorList.Count == 2);

            VerifyNodeStatus2((LocalCallDescriptorForPostStatus)localCallDescriptorList[0]);
            VerifyPostMessagesToHost((LocalCallDescriptorForPostLoggingMessagesToHost)localCallDescriptorList[1], numberOfEvents);
            writeSharedMemory.Reset();
            readSharedMemory.Reset();
            readSharedMemory = null;
            writeSharedMemory = null;
        }
Пример #7
0
        public void TestItemsInandOutOfSharedMemory()
        {
            string name = Guid.NewGuid().ToString();
            // Create the shared memory buffer
            SharedMemory readSharedMemory =
                  new SharedMemory
                  (
                        name,
                        SharedMemoryType.ReadOnly,
                        true
                  );


            SharedMemory writeSharedMemory =
                new SharedMemory
                (
                    name,
                    SharedMemoryType.WriteOnly,
                    true
                );

            DualQueue<LocalCallDescriptor> queue = new DualQueue<LocalCallDescriptor>();
            DualQueue<LocalCallDescriptor> hiPriQueue = new DualQueue<LocalCallDescriptor>();
            LocalCallDescriptorForPostLoggingMessagesToHost LargeLogEvent = CreatePostMessageCallDescriptor(1);
            LocalCallDescriptorForUpdateNodeSettings updateNodeSettings = new LocalCallDescriptorForUpdateNodeSettings(true, true, true);
            LocalCallDescriptorForPostBuildResult buildResult = new LocalCallDescriptorForPostBuildResult(CreateBuildResult());
            LocalCallDescriptorForPostBuildRequests buildRequests = new LocalCallDescriptorForPostBuildRequests(CreateBuildRequest());
            LocalCallDescriptorForRequestStatus requestStatus = new LocalCallDescriptorForRequestStatus(4);
            LocalCallDescriptorForPostStatus nodeStatusNoExcept = new LocalCallDescriptorForPostStatus(new NodeStatus(1, true, 2, 3, 4, true));
            LocalCallDescriptorForPostStatus nodeStatusExcept = new LocalCallDescriptorForPostStatus(new NodeStatus(new Exception("I am bad")));
            LocalCallDescriptorForShutdownNode shutdownNode = new LocalCallDescriptorForShutdownNode(Node.NodeShutdownLevel.BuildCompleteSuccess, true);
            LocalCallDescriptorForShutdownComplete shutdownComplete = new LocalCallDescriptorForShutdownComplete(Node.NodeShutdownLevel.BuildCompleteFailure, 0);
            LocalCallDescriptorForInitializationComplete initializeComplete = new LocalCallDescriptorForInitializationComplete(99);

            BuildPropertyGroup propertyGroup = new BuildPropertyGroup();
            BuildProperty propertyToAdd = new BuildProperty("PropertyName", "Value");
            propertyGroup.SetProperty(propertyToAdd);
            CacheEntry[] entries = CreateCacheEntries();
            LocalCallDescriptorForGettingCacheEntriesFromHost getCacheEntries = new LocalCallDescriptorForGettingCacheEntriesFromHost(new string[] { "Hi", "Hello" }, "Name", propertyGroup, "3.5", CacheContentType.Properties);
            LocalCallDescriptorForPostingCacheEntriesToHost postCacheEntries = new LocalCallDescriptorForPostingCacheEntriesToHost(entries, "ScopeName", propertyGroup, "3.5", CacheContentType.BuildResults);
            LocalReplyCallDescriptor replyDescriptor1 = new LocalReplyCallDescriptor(1, entries);
            LocalReplyCallDescriptor replyDescriptor2 = new LocalReplyCallDescriptor(6, "Foo");

            IDictionary environmentVariables = Environment.GetEnvironmentVariables();
            Hashtable environmentVariablesHashtable = new Hashtable(environmentVariables);

            string className = "Class";
            string loggerAssemblyName = "Class";
            string loggerFileAssembly = null;
            string loggerSwitchParameters = "Class";
            LoggerVerbosity verbosity = LoggerVerbosity.Detailed;
            LoggerDescription description = new LoggerDescription(className, loggerAssemblyName, loggerFileAssembly, loggerSwitchParameters, verbosity);
            LocalCallDescriptorForInitializeNode initializeNode = new LocalCallDescriptorForInitializeNode(environmentVariablesHashtable, new LoggerDescription[] { description }, 4, propertyGroup, ToolsetDefinitionLocations.ConfigurationFile, 5, String.Empty);

            queue.Enqueue(LargeLogEvent);
            queue.Enqueue(updateNodeSettings);
            queue.Enqueue(buildResult);
            queue.Enqueue(buildRequests);
            queue.Enqueue(requestStatus);
            queue.Enqueue(nodeStatusNoExcept);
            queue.Enqueue(nodeStatusExcept);
            queue.Enqueue(shutdownNode);
            queue.Enqueue(shutdownComplete);
            queue.Enqueue(initializeComplete);
            queue.Enqueue(getCacheEntries);
            queue.Enqueue(postCacheEntries);
            queue.Enqueue(replyDescriptor1);
            queue.Enqueue(replyDescriptor2);
            queue.Enqueue(initializeNode);
            writeSharedMemory.Write(queue, hiPriQueue, false);

            IList localCallDescriptorList = readSharedMemory.Read();
            Assert.IsTrue(localCallDescriptorList.Count == 15);

            LocalCallDescriptorForPostLoggingMessagesToHost messageCallDescriptor = localCallDescriptorList[0] as LocalCallDescriptorForPostLoggingMessagesToHost;
            VerifyPostMessagesToHost(messageCallDescriptor, 1);

            LocalCallDescriptorForUpdateNodeSettings updateSettingsCallDescriptor = localCallDescriptorList[1] as LocalCallDescriptorForUpdateNodeSettings;
            VerifyUpdateSettings(updateSettingsCallDescriptor);

            LocalCallDescriptorForPostBuildResult buildResultCallDescriptor = localCallDescriptorList[2] as LocalCallDescriptorForPostBuildResult;
            CompareBuildResult(buildResultCallDescriptor);

            LocalCallDescriptorForPostBuildRequests buildRequestsCallDescriptor = localCallDescriptorList[3] as LocalCallDescriptorForPostBuildRequests;
            ComparebuildRequests(buildRequestsCallDescriptor);

            LocalCallDescriptorForRequestStatus requestStatusCallDescriptor = localCallDescriptorList[4] as LocalCallDescriptorForRequestStatus;
            Assert.IsTrue(requestStatusCallDescriptor.RequestId == 4);

            LocalCallDescriptorForPostStatus nodeStatus1CallDescriptor = localCallDescriptorList[5] as LocalCallDescriptorForPostStatus;
            VerifyNodeStatus1(nodeStatus1CallDescriptor);

            LocalCallDescriptorForPostStatus nodeStatus2CallDescriptor = localCallDescriptorList[6] as LocalCallDescriptorForPostStatus;
            VerifyNodeStatus2(nodeStatus2CallDescriptor);

            LocalCallDescriptorForShutdownNode shutdownNodeCallDescriptor = localCallDescriptorList[7] as LocalCallDescriptorForShutdownNode;
            Assert.IsTrue(shutdownNodeCallDescriptor.ShutdownLevel == Node.NodeShutdownLevel.BuildCompleteSuccess);
            Assert.IsTrue(shutdownNodeCallDescriptor.ExitProcess);

            LocalCallDescriptorForShutdownComplete shutdownNodeCompleteCallDescriptor = localCallDescriptorList[8] as LocalCallDescriptorForShutdownComplete;
            Assert.IsTrue(shutdownNodeCompleteCallDescriptor.ShutdownLevel == Node.NodeShutdownLevel.BuildCompleteFailure);

            LocalCallDescriptorForInitializationComplete initializeCompleteCallDescriptor = localCallDescriptorList[9] as LocalCallDescriptorForInitializationComplete;
            Assert.IsTrue(initializeCompleteCallDescriptor.ProcessId == 99);

            LocalCallDescriptorForGettingCacheEntriesFromHost getCacheEntriesCallDescriptor = localCallDescriptorList[10] as LocalCallDescriptorForGettingCacheEntriesFromHost;
            VerifyGetCacheEntryFromHost(getCacheEntriesCallDescriptor);

            LocalCallDescriptorForPostingCacheEntriesToHost postCacheEntriesCallDescriptor = localCallDescriptorList[11] as LocalCallDescriptorForPostingCacheEntriesToHost;
            Assert.IsTrue(string.Compare(postCacheEntriesCallDescriptor.ScopeName, "ScopeName", StringComparison.OrdinalIgnoreCase) == 0);
            Assert.IsTrue(string.Compare(postCacheEntriesCallDescriptor.ScopeProperties["PropertyName"].Value, "Value", StringComparison.OrdinalIgnoreCase) == 0);
            Assert.IsTrue(string.Compare(postCacheEntriesCallDescriptor.ScopeToolsVersion, "3.5", StringComparison.OrdinalIgnoreCase) == 0);
            Assert.IsTrue(postCacheEntriesCallDescriptor.ContentType == CacheContentType.BuildResults);
            VerifyGetCacheEntries(postCacheEntriesCallDescriptor.Entries);

            LocalReplyCallDescriptor reply1CallDescriptor = localCallDescriptorList[12] as LocalReplyCallDescriptor;
            Assert.IsTrue(reply1CallDescriptor.RequestingCallNumber == 1);
            VerifyGetCacheEntries((CacheEntry[])reply1CallDescriptor.ReplyData);

            LocalReplyCallDescriptor reply2CallDescriptor = localCallDescriptorList[13] as LocalReplyCallDescriptor;
            Assert.IsTrue(reply2CallDescriptor.RequestingCallNumber == 6);
            Assert.IsTrue(string.Compare("Foo", (string)reply2CallDescriptor.ReplyData, StringComparison.OrdinalIgnoreCase) == 0);

            LocalCallDescriptorForInitializeNode initializeCallDescriptor = localCallDescriptorList[14] as LocalCallDescriptorForInitializeNode;
            Assert.IsTrue(initializeCallDescriptor.ParentProcessId == 5);
            Assert.IsTrue(initializeCallDescriptor.NodeId == 4);
            Assert.IsTrue(initializeCallDescriptor.ToolsetSearchLocations == ToolsetDefinitionLocations.ConfigurationFile);
            Assert.IsTrue(string.Compare(initializeCallDescriptor.ParentGlobalProperties["PropertyName"].Value, "Value", StringComparison.OrdinalIgnoreCase) == 0);
            Assert.IsTrue(string.Compare(initializeCallDescriptor.NodeLoggers[0].Name, "Class", StringComparison.OrdinalIgnoreCase) == 0);

            IDictionary variables = Environment.GetEnvironmentVariables();

            Assert.IsTrue(variables.Count == initializeCallDescriptor.EnvironmentVariables.Count);
            foreach (string key in variables.Keys)
            {
                Assert.IsTrue(string.Compare((string)initializeCallDescriptor.EnvironmentVariables[key], (string)variables[key], StringComparison.OrdinalIgnoreCase) == 0);
            }

            writeSharedMemory.Reset();
            readSharedMemory.Reset();
            readSharedMemory = null;
            writeSharedMemory = null;
        }
Пример #8
0
        /// <summary>
        /// This method is called to post the status of the node. Because status is used
        /// to report errors and to respond to inactivity notices, we use a separate queue
        /// to deliver status event to the shared memory. Otherwise status maybe be delayed
        /// if it is stuck behind a large number of other events. We also wait for the status
        /// to be sent before returning.
        /// </summary>
        public void PostStatus(int nodeId, NodeStatus nodeStatus, bool blockUntilSent)
        {
            // We should not be on the running on the callback writer thread
            ErrorUtilities.VerifyThrow(Thread.CurrentThread != writerThread, "Should never call this function from the writer thread");

            LocalCallDescriptorForPostStatus callDescriptor =
                new LocalCallDescriptorForPostStatus(nodeStatus);
            nodeHiPriCommandQueue.Enqueue(callDescriptor);

            // We need to block until the event we posted has been processed, but if the writer thread
            // exit due to an error the shared memory is no longer valid so there is no way to send the message
            while (blockUntilSent && !writerThreadHasExited && nodeHiPriCommandQueue.Count > 0)
            {
                nodeHiPriCommandQueue.QueueEmptyEvent.WaitOne(1000, false);

                // Check if the communication threads are supposed to exit
                if (exitCommunicationThreads.WaitOne(0, false))
                {
                    break;
                }
            }
        }