/// <summary> /// Prevent any additional threads from starting and return once all existing workers have completed. /// </summary> /// <param name="threadShutdownTimeoutMS"></param> public void EndShutdown(int threadShutdownTimeoutMS = 1000) { #if NETFX_CORE foreach (var pair in scheduledTasks) { if (!pair.Value.Wait(threadShutdownTimeoutMS)) { taskCancellationTokens[pair.Key].Cancel(); if (!pair.Value.Wait(threadShutdownTimeoutMS)) { LogTools.LogException(new CommsSetupShutdownException("Managed threadpool shutdown error"), "ManagedThreadPoolShutdownError"); } } } #else List <Thread> allWorkerThreads = new List <Thread>(); lock (SyncRoot) { foreach (var thread in threadDict) { workerInfoDict[thread.Key].ThreadSignal.Set(); allWorkerThreads.Add(thread.Value); } } //Wait for all threads to finish foreach (Thread thread in allWorkerThreads) { try { if (!thread.Join(threadShutdownTimeoutMS)) { thread.Abort(); } } catch (Exception ex) { LogTools.LogException(ex, "ManagedThreadPoolShutdownError"); } } #endif lock (SyncRoot) { jobQueue.Clear(); taskCancellationTokens.Clear(); scheduledTasks.Clear(); shutdown = false; } }
/// <summary> /// Shutdown any background threads in the host tools /// </summary> /// <param name="threadShutdownTimeoutMS"></param> internal static void ShutdownThreads(int threadShutdownTimeoutMS = 1000) { #if !WINDOWS_PHONE && !ANDROID && !NETFX_CORE try { if (NetworkLoadThread != null) { NetworkLoadThreadWait.Set(); if (!NetworkLoadThread.Join(threadShutdownTimeoutMS)) { NetworkLoadThread.Abort(); throw new CommsSetupShutdownException("Timeout waiting for NetworkLoadThread thread to shutdown after " + threadShutdownTimeoutMS.ToString() + " ms. "); } } } catch (Exception ex) { LogTools.LogException(ex, "CommsShutdownError"); } #endif }
/// <summary> /// Takes a network load snapshot (CurrentNetworkLoad) every NetworkLoadUpdateWindowMS /// </summary> private static void NetworkLoadWorker() { NetworkLoadThreadWait = new ManualResetEvent(false); //Get all interfaces NetworkInterface[] interfacesToUse = NetworkInterface.GetAllNetworkInterfaces(); long[] startSent, startReceived, endSent, endReceived; while (!NetworkComms.commsShutdown) { try { //we need to look at the load across all adaptors, by default we will probably choose the adaptor with the highest usage DateTime startTime = DateTime.Now; IPv4InterfaceStatistics[] stats = new IPv4InterfaceStatistics[interfacesToUse.Length]; startSent = new long[interfacesToUse.Length]; startReceived = new long[interfacesToUse.Length]; for (int i = 0; i < interfacesToUse.Length; ++i) { stats[i] = interfacesToUse[i].GetIPv4Statistics(); startSent[i] = stats[i].BytesSent; startReceived[i] = stats[i].BytesReceived; } if (NetworkComms.commsShutdown) { return; } //Thread.Sleep(NetworkLoadUpdateWindowMS); #if NET2 NetworkLoadThreadWait.WaitOne(NetworkLoadUpdateWindowMS, false); #else NetworkLoadThreadWait.WaitOne(NetworkLoadUpdateWindowMS); #endif if (NetworkComms.commsShutdown) { return; } stats = new IPv4InterfaceStatistics[interfacesToUse.Length]; endSent = new long[interfacesToUse.Length]; endReceived = new long[interfacesToUse.Length]; for (int i = 0; i < interfacesToUse.Length; ++i) { stats[i] = interfacesToUse[i].GetIPv4Statistics(); endSent[i] = stats[i].BytesSent; endReceived[i] = stats[i].BytesReceived; } DateTime endTime = DateTime.Now; List <double> outUsage = new List <double>(); List <double> inUsage = new List <double>(); for (int i = 0; i < startSent.Length; i++) { outUsage.Add((double)(endSent[i] - startSent[i]) / ((double)(InterfaceLinkSpeed * (endTime - startTime).TotalMilliseconds) / 8000)); inUsage.Add((double)(endReceived[i] - startReceived[i]) / ((double)(InterfaceLinkSpeed * (endTime - startTime).TotalMilliseconds) / 8000)); } //double loadValue = Math.Max(outUsage.Max(), inUsage.Max()); double inMax = double.MinValue, outMax = double.MinValue; for (int i = 0; i < startSent.Length; ++i) { if (inUsage[i] > inMax) { inMax = inUsage[i]; } if (outUsage[i] > outMax) { outMax = outUsage[i]; } } //If either of the usage levels have gone above 2 it suggests we are most likely on a faster connection that we think //As such we will bump the interface link speed up to 1Gbps so that future load calculations more accurately reflect the //actual load. if (inMax > 2 || outMax > 2) { InterfaceLinkSpeed = 950000000; } //Limit to one CurrentNetworkLoadIncoming = (inMax > 1 ? 1 : inMax); CurrentNetworkLoadOutgoing = (outMax > 1 ? 1 : outMax); currentNetworkLoadValuesIncoming.AddValue(CurrentNetworkLoadIncoming); currentNetworkLoadValuesOutgoing.AddValue(CurrentNetworkLoadOutgoing); //We can only have up to 255 seconds worth of data in the average list int maxListSize = (int)(255000.0 / NetworkLoadUpdateWindowMS); currentNetworkLoadValuesIncoming.TrimList(maxListSize); currentNetworkLoadValuesOutgoing.TrimList(maxListSize); } catch (Exception ex) { //There is no need to log if the exception is due to a change in interfaces if (ex.GetType() != typeof(NetworkInformationException)) { LogTools.LogException(ex, "NetworkLoadWorker"); } //It may be the interfaces available to the OS have changed so we will reset them here interfacesToUse = NetworkInterface.GetAllNetworkInterfaces(); //If an error has happened we don't want to thrash the problem, we wait for 5 seconds and hope whatever was wrong goes away Thread.Sleep(5000); } } }