From 29c590a972c3fb111e9f7e087ff40ae3c0a3a98c Mon Sep 17 00:00:00 2001 From: Terry MacDonald Date: Wed, 18 May 2022 21:32:33 +1200 Subject: [PATCH] Fixed High CPU issue Replaced Task.Delay with Thread.Sleep as we were incorrectly pausing the monitoring thread. Should fix #110. --- DisplayMagician/Program.cs | 2 +- DisplayMagician/Properties/AssemblyInfo.cs | 4 +- .../DisplayMagicianShared.csproj | 1 + DisplayMagicianShared/ExtensionMethods.cs | 288 ++++++++++++++++++ 4 files changed, 292 insertions(+), 3 deletions(-) create mode 100644 DisplayMagicianShared/ExtensionMethods.cs diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs index fc26da0..fb815b7 100644 --- a/DisplayMagician/Program.cs +++ b/DisplayMagician/Program.cs @@ -1134,7 +1134,7 @@ namespace DisplayMagician { //taskToRun.RunSynchronously(); while (!taskToRun.IsCompleted) { - Task.Delay(1000); + Thread.Sleep(1000); Application.DoEvents(); if (Program.AppCancellationTokenSource.Token.IsCancellationRequested) { diff --git a/DisplayMagician/Properties/AssemblyInfo.cs b/DisplayMagician/Properties/AssemblyInfo.cs index 93e872a..e5f806d 100644 --- a/DisplayMagician/Properties/AssemblyInfo.cs +++ b/DisplayMagician/Properties/AssemblyInfo.cs @@ -26,8 +26,8 @@ using System.Resources; [assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")] // Version information -[assembly: AssemblyVersion("2.3.1.65")] -[assembly: AssemblyFileVersion("2.3.1.65")] +[assembly: AssemblyVersion("2.3.1.67")] +[assembly: AssemblyFileVersion("2.3.1.67")] [assembly: NeutralResourcesLanguageAttribute( "en" )] [assembly: CLSCompliant(true)] diff --git a/DisplayMagicianShared/DisplayMagicianShared.csproj b/DisplayMagicianShared/DisplayMagicianShared.csproj index 4d924e1..ae16c6a 100644 --- a/DisplayMagicianShared/DisplayMagicianShared.csproj +++ b/DisplayMagicianShared/DisplayMagicianShared.csproj @@ -55,6 +55,7 @@ + diff --git a/DisplayMagicianShared/ExtensionMethods.cs b/DisplayMagicianShared/ExtensionMethods.cs new file mode 100644 index 0000000..be55d69 --- /dev/null +++ b/DisplayMagicianShared/ExtensionMethods.cs @@ -0,0 +1,288 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace DisplayMagicianShared +{ + internal static class ExtensionMethods + { + /// A delegate callback throws an exception. + /*public static Type[] Accepts(this Delegate @delegate, int parameterIndex = 0) + { + Type[] types = null; + var parameters = @delegate.GetType().GetMethod("Invoke")?.GetParameters(); + + if (parameterIndex > 0) + { + if (parameters?.Length >= parameterIndex) + { + types = parameters[parameterIndex - 1].GetCustomAttributes(typeof(AcceptsAttribute), true) + .Cast() + .FirstOrDefault()? + .Types; + } + } + + if (types == null) + { + if (parameters != null) + { + types = parameters.SelectMany(param => param.GetCustomAttributes(typeof(AcceptsAttribute), true)) + .Cast() + .FirstOrDefault()? + .Types; + } + else + { + types = @delegate.GetType().GetCustomAttributes(typeof(AcceptsAttribute), false) + .Cast() + .FirstOrDefault()? + .Types; + } + } + + return types ?? new Type[0]; + }*/ + + /*public static IEnumerable AllocateAll(this IEnumerable allocatableArray) + { + foreach ( + var allocatable in + allocatableArray.Where(item => item.GetType().GetInterfaces().Contains(typeof(IAllocatable)))) + { + var boxedCopy = (IAllocatable)allocatable; + boxedCopy.Allocate(); + + yield return (T)boxedCopy; + } + } +*/ + public static TResult BitWiseConvert(T source) + where TResult : struct, IConvertible + where T : struct, IConvertible + { + if (typeof(T) == typeof(TResult)) + { + return (TResult)(object)source; + } + + var sourceSize = Marshal.SizeOf(typeof(T)); + var destinationSize = Marshal.SizeOf(typeof(TResult)); + var minSize = Math.Min(sourceSize, destinationSize); + var sourcePointer = Marshal.AllocHGlobal(sourceSize); + Marshal.StructureToPtr(source, sourcePointer, false); + var bytes = new byte[destinationSize]; + + if (BitConverter.IsLittleEndian) + { + Marshal.Copy(sourcePointer, bytes, 0, minSize); + } + else + { + Marshal.Copy(sourcePointer + (sourceSize - minSize), bytes, destinationSize - minSize, minSize); + } + + Marshal.FreeHGlobal(sourcePointer); + var destinationPointer = Marshal.AllocHGlobal(destinationSize); + Marshal.Copy(bytes, 0, destinationPointer, destinationSize); + var destination = (TResult)Marshal.PtrToStructure(destinationPointer, typeof(TResult)); + Marshal.FreeHGlobal(destinationPointer); + + return destination; + } + + /*public static void DisposeAll(this IEnumerable disposableArray) + { + foreach ( + var disposable in + disposableArray.Where( + item => + item.GetType() + .GetInterfaces() + .Any(i => i == typeof(IDisposable) || i == typeof(IAllocatable)))) + { + ((IDisposable)disposable).Dispose(); + } + }*/ + + public static bool GetBit(this T integer, int index) where T : struct, IConvertible + { + var bigInteger = BitWiseConvert(integer); + var mask = 1ul << index; + + return (bigInteger & mask) > 0; + } + + public static ulong GetBits(this T integer, int index, int count) where T : struct, IConvertible + { + var bigInteger = BitWiseConvert(integer); + + if (index > 0) + { + bigInteger >>= index; + } + + count = 64 - count; + bigInteger <<= count; + bigInteger >>= count; + + return bigInteger; + } + + + // ReSharper disable once FunctionComplexityOverflow + // ReSharper disable once ExcessiveIndentation + /*public static T Instantiate(this Type type) + { + object instance = default(T); + + try + { + if (type.IsValueType) + { + instance = (T)Activator.CreateInstance(type); + } + + if (type.GetInterfaces().Any(i => i == typeof(IInitializable) || i == typeof(IAllocatable))) + { + foreach (var field in type.GetRuntimeFields()) + { + if (field.IsStatic || field.IsLiteral) + { + continue; + } + + if (field.FieldType == typeof(StructureVersion)) + { + var version = + type.GetCustomAttributes(typeof(StructureVersionAttribute), true) + .Cast() + .FirstOrDefault()? + .VersionNumber; + field.SetValue(instance, + version.HasValue ? new StructureVersion(version.Value, type) : new StructureVersion()); + } + else if (field.FieldType.IsArray) + { + var size = + field.GetCustomAttributes(typeof(MarshalAsAttribute), false) + .Cast() + .FirstOrDefault(attribute => attribute.Value != UnmanagedType.LPArray)? + .SizeConst; + var arrayType = field.FieldType.GetElementType(); + var array = Array.CreateInstance( + arrayType ?? throw new InvalidOperationException("Field type is null."), size ?? 0); + + if (arrayType.IsValueType) + { + for (var i = 0; i < array.Length; i++) + { + var obj = arrayType.Instantiate(); + array.SetValue(obj, i); + } + } + + field.SetValue(instance, array); + } + else if (field.FieldType == typeof(string)) + { + var isByVal = field.GetCustomAttributes(typeof(MarshalAsAttribute), false) + .Cast() + .Any(attribute => attribute.Value == UnmanagedType.ByValTStr); + + if (isByVal) + { + field.SetValue(instance, string.Empty); + } + } + else if (field.FieldType.IsValueType) + { + var isByRef = field.GetCustomAttributes(typeof(MarshalAsAttribute), false) + .Cast() + .Any(attribute => attribute.Value == UnmanagedType.LPStruct); + + if (!isByRef) + { + var value = field.FieldType.Instantiate(); + field.SetValue(instance, value); + } + } + } + } + } + catch + { + // ignored + } + + return (T)instance; + }*/ + + public static T[] Repeat(this T structure, int count) + { + return Enumerable.Range(0, count).Select(i => structure).ToArray(); + } + + public static T SetBit(this T integer, int index, bool value) where T : struct, IConvertible + { + var bigInteger = BitWiseConvert(integer); + + var mask = 1ul << index; + var newInteger = value ? bigInteger | mask : bigInteger & ~mask; + + return BitWiseConvert(newInteger); + } + + // ReSharper disable once TooManyArguments + public static T SetBits(this T integer, int index, int count, ulong value) where T : struct, IConvertible + { + var bigInteger = BitWiseConvert(integer); + + count = 64 - count; + value <<= count; + value >>= count - index; + + bigInteger |= value; + + return BitWiseConvert(bigInteger); + } + + public static byte[] ToByteArray(this T structure) where T : struct + { + var size = Marshal.SizeOf(typeof(T)); + var array = new byte[size]; + var pointer = Marshal.AllocHGlobal(size); + + try + { + Marshal.StructureToPtr(structure, pointer, true); + Marshal.Copy(pointer, array, 0, size); + + return array; + } + finally + { + Marshal.FreeHGlobal(pointer); + } + } + + public static T ToStructure(this byte[] byteArray) where T : struct + { + var size = Marshal.SizeOf(typeof(T)); + var pointer = Marshal.AllocHGlobal(size); + + try + { + Marshal.Copy(byteArray, 0, pointer, Math.Min(byteArray.Length, size)); + + return (T)Marshal.PtrToStructure(pointer, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(pointer); + } + } + } +} \ No newline at end of file