diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.FreeBSD.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.FreeBSD.cs index 3fd30ba9ba2c50..5686ae9db65fa9 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.FreeBSD.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.FreeBSD.cs @@ -7,11 +7,6 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// private ThreadPriorityLevel PriorityLevelCore { get @@ -29,51 +24,16 @@ private ThreadPriorityLevel PriorityLevelCore // all threads e.g. reflects process start. This may be re-visited later. private static DateTime GetStartTime() => throw new PlatformNotSupportedException(); - /// - /// Returns the amount of time the associated thread has spent utilizing the CPU. - /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and - /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan TotalProcessorTime + private TimeSpan GetTotalProcessorTime() { - get - { - Interop.Process.proc_stats stat = Interop.Process.GetThreadInfo(_processId, Id); - return Process.TicksToTimeSpan(stat.userTime + stat.systemTime); - } + Interop.Process.proc_stats stat = Interop.Process.GetThreadInfo(_processId, Id); + return Process.TicksToTimeSpan(stat.userTime + stat.systemTime); } - /// - /// Returns the amount of time the associated thread has spent running code - /// inside the application (not the operating system core). - /// - public TimeSpan UserProcessorTime - { - get - { - Interop.Process.proc_stats stat = Interop.Process.GetThreadInfo(_processId, Id); - return Process.TicksToTimeSpan(stat.userTime); - } - } - - /// - /// Returns the amount of time the thread has spent running code inside the operating - /// system core. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan PrivilegedProcessorTime - { - get - { - Interop.Process.proc_stats stat = Interop.Process.GetThreadInfo(_processId, Id); - return Process.TicksToTimeSpan(stat.systemTime); - } + private TimeSpan GetUserProcessorTime() + => Process.TicksToTimeSpan(Interop.Process.GetThreadInfo(_processId, Id).userTime); - } + private TimeSpan GetPrivilegedProcessorTime() + => Process.TicksToTimeSpan(Interop.Process.GetThreadInfo(_processId, Id).systemTime); } } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Linux.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Linux.cs index e9a8bd92e04a9f..2941a4b352044c 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Linux.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Linux.cs @@ -9,11 +9,6 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// private ThreadPriorityLevel PriorityLevelCore { // This mapping is relatively arbitrary. 0 is normal based on the man page, @@ -29,56 +24,17 @@ private ThreadPriorityLevel PriorityLevelCore } } - /// - /// Returns the amount of time the thread has spent running code inside the operating - /// system core. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan PrivilegedProcessorTime - { - get - { - Interop.procfs.ParsedStat stat = GetStat(); - return Process.TicksToTimeSpan(stat.stime); - } - } + private TimeSpan GetPrivilegedProcessorTime() => Process.TicksToTimeSpan(GetStat().stime); private DateTime GetStartTime() => Process.BootTimeToDateTime(Process.TicksToTimeSpan(GetStat().starttime)); - /// - /// Returns the amount of time the associated thread has spent utilizing the CPU. - /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and - /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan TotalProcessorTime + private TimeSpan GetTotalProcessorTime() { - get - { - Interop.procfs.ParsedStat stat = GetStat(); - return Process.TicksToTimeSpan(stat.utime + stat.stime); - } + Interop.procfs.ParsedStat stat = GetStat(); + return Process.TicksToTimeSpan(stat.utime + stat.stime); } - /// - /// Returns the amount of time the associated thread has spent running code - /// inside the application (not the operating system core). - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan UserProcessorTime - { - get - { - Interop.procfs.ParsedStat stat = GetStat(); - return Process.TicksToTimeSpan(stat.utime); - } - } + private TimeSpan GetUserProcessorTime() => Process.TicksToTimeSpan(GetStat().utime); private Interop.procfs.ParsedStat GetStat() { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.OSX.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.OSX.cs index 4d96a4b294d5c0..599fe6d05b7355 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.OSX.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.OSX.cs @@ -7,11 +7,6 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// private static ThreadPriorityLevel PriorityLevelCore { // Does not appear to be a POSIX API to do this on macOS. @@ -21,42 +16,17 @@ private static ThreadPriorityLevel PriorityLevelCore set { throw new PlatformNotSupportedException(SR.ThreadPriorityNotSupported); } } - /// - /// Returns the amount of time the thread has spent running code inside the operating - /// system core. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan PrivilegedProcessorTime => new TimeSpan((long)GetThreadInfo().pth_system_time); + private TimeSpan GetPrivilegedProcessorTime() => new TimeSpan((long)GetThreadInfo().pth_system_time); private static DateTime GetStartTime() => throw new PlatformNotSupportedException(); // macOS does not provide a way to get this data - /// - /// Returns the amount of time the associated thread has spent using the CPU. - /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and - /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan TotalProcessorTime + private TimeSpan GetTotalProcessorTime() { - get - { - Interop.libproc.proc_threadinfo info = GetThreadInfo(); - return new TimeSpan((long)(info.pth_user_time + info.pth_system_time)); - } + Interop.libproc.proc_threadinfo info = GetThreadInfo(); + return new TimeSpan((long)(info.pth_user_time + info.pth_system_time)); } - /// - /// Returns the amount of time the associated thread has spent running code - /// inside the application (not the operating system core). - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan UserProcessorTime => new TimeSpan((long)GetThreadInfo().pth_user_time); + private TimeSpan GetUserProcessorTime() => new TimeSpan((long)GetThreadInfo().pth_user_time); private Interop.libproc.proc_threadinfo GetThreadInfo() { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Unix.cs index 0d954fa39a74bf..c4b67e13474e6f 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Unix.cs @@ -7,44 +7,23 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// Sets the processor that this thread would ideally like to run on. - public int IdealProcessor + private static void SetIdealProcessor(int value) { - set - { - // Nop. This is a hint, and there's no good match for the Windows concept. - } + // Nop. This is a hint, and there's no good match for the Windows concept. } - /// - /// Resets the ideal processor so there is no ideal processor for this thread (e.g. - /// any processor is ideal). - /// - public void ResetIdealProcessor() + private static void ResetIdealProcessorCore() { - // Nop. This is a hint, and there's no good match for the Windows concept. + // Nop. This is a hint, and there's no good match for the Windows concept. } - /// - /// Returns or sets whether this thread would like a priority boost if the user interacts - /// with user interface associated with this thread. - /// private static bool PriorityBoostEnabledCore { get { return false; } set { } // Nop } - /// - /// Sets which processors the associated thread is allowed to be scheduled to run on. - /// Each processor is represented as a bit: bit 0 is processor one, bit 1 is processor - /// two, etc. For example, the value 1 means run on processor one, 2 means run on - /// processor two, 3 means run on processor one or two. - /// - [SupportedOSPlatform("windows")] - public IntPtr ProcessorAffinity - { - set { throw new PlatformNotSupportedException(); } // No ability to change the affinity of a thread in an arbitrary process - } + private static void SetProcessorAffinity(IntPtr value) + => throw new PlatformNotSupportedException(); // No ability to change the affinity of a thread in an arbitrary process } } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Windows.cs index 7f67d4c861d213..ddbf1e88b33201 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.Windows.cs @@ -9,36 +9,24 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// Sets the processor that this thread would ideally like to run on. - public int IdealProcessor + private void SetIdealProcessor(int value) { - set + using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION)) { - using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION)) + if (Interop.Kernel32.SetThreadIdealProcessor(threadHandle, value) < 0) { - if (Interop.Kernel32.SetThreadIdealProcessor(threadHandle, value) < 0) - { - throw new Win32Exception(); - } + throw new Win32Exception(); } } } - /// - /// Resets the ideal processor so there is no ideal processor for this thread (e.g. - /// any processor is ideal). - /// - public void ResetIdealProcessor() + private void ResetIdealProcessorCore() { // MAXIMUM_PROCESSORS == 32 on 32-bit or 64 on 64-bit, and means the thread has no preferred processor int MAXIMUM_PROCESSORS = IntPtr.Size == 4 ? 32 : 64; IdealProcessor = MAXIMUM_PROCESSORS; } - /// - /// Returns or sets whether this thread would like a priority boost if the user interacts - /// with user interface associated with this thread. - /// private bool PriorityBoostEnabledCore { get @@ -63,11 +51,6 @@ private bool PriorityBoostEnabledCore } } - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// private ThreadPriorityLevel PriorityLevelCore { get @@ -94,65 +77,24 @@ private ThreadPriorityLevel PriorityLevelCore } } - /// - /// Sets which processors the associated thread is allowed to be scheduled to run on. - /// Each processor is represented as a bit: bit 0 is processor one, bit 1 is processor - /// two, etc. For example, the value 1 means run on processor one, 2 means run on - /// processor two, 3 means run on processor one or two. - /// - [SupportedOSPlatform("windows")] - public IntPtr ProcessorAffinity + private void SetProcessorAffinity(IntPtr value) { - set + using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION | Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) { - using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION | Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) + if (Interop.Kernel32.SetThreadAffinityMask(threadHandle, value) == IntPtr.Zero) { - if (Interop.Kernel32.SetThreadAffinityMask(threadHandle, value) == IntPtr.Zero) - { - throw new Win32Exception(); - } + throw new Win32Exception(); } } } - /// - /// Returns the amount of time the thread has spent running code inside the operating - /// system core. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan PrivilegedProcessorTime - { - get { return GetThreadTimes().PrivilegedProcessorTime; } - } + private TimeSpan GetPrivilegedProcessorTime() => GetThreadTimes().PrivilegedProcessorTime; private DateTime GetStartTime() => GetThreadTimes().StartTime; - /// - /// Returns the amount of time the associated thread has spent utilizing the CPU. - /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and - /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan TotalProcessorTime - { - get { return GetThreadTimes().TotalProcessorTime; } - } + private TimeSpan GetTotalProcessorTime() => GetThreadTimes().TotalProcessorTime; - /// - /// Returns the amount of time the associated thread has spent running code - /// inside the application (not the operating system core). - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan UserProcessorTime - { - get { return GetThreadTimes().UserProcessorTime; } - } + private TimeSpan GetUserProcessorTime() => GetThreadTimes().UserProcessorTime; /// Gets timing information for the thread. private ProcessThreadTimes GetThreadTimes() diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.cs index 215e67e8928d56..33e9b67b5d7085 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.cs @@ -6,13 +6,11 @@ namespace System.Diagnostics { - /// - /// - /// Represents a Win32 thread. This can be used to obtain - /// information about the thread, such as it's performance characteristics. This is - /// returned from the System.Diagnostics.Process.ProcessThread property of the System.Diagnostics.Process component. - /// - /// + /// + /// Represents a Win32 thread. This can be used to obtain + /// information about the thread, such as it's performance characteristics. This is + /// returned from the System.Diagnostics.Process.ProcessThread property of the System.Diagnostics.Process component. + /// [Designer("System.Diagnostics.Design.ProcessThreadDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public partial class ProcessThread : Component { @@ -22,10 +20,6 @@ public partial class ProcessThread : Component private bool? _priorityBoostEnabled; private ThreadPriorityLevel? _priorityLevel; - /// - /// Internal constructor. - /// - /// internal ProcessThread(bool isRemoteMachine, int processId, ThreadInfo threadInfo) { _isRemoteMachine = isRemoteMachine; @@ -33,37 +27,35 @@ internal ProcessThread(bool isRemoteMachine, int processId, ThreadInfo threadInf _threadInfo = threadInfo; } - /// - /// Returns the base priority of the thread which is computed by combining the - /// process priority class with the priority level of the associated thread. - /// + /// + /// Returns the base priority of the thread which is computed by combining the + /// process priority class with the priority level of the associated thread. + /// public int BasePriority { get { return _threadInfo._basePriority; } } - /// - /// The current priority indicates the actual priority of the associated thread, - /// which may deviate from the base priority based on how the OS is currently - /// scheduling the thread. - /// + /// + /// The current priority indicates the actual priority of the associated thread, + /// which may deviate from the base priority based on how the OS is currently + /// scheduling the thread. + /// public int CurrentPriority { get { return _threadInfo._currentPriority; } } - /// - /// Returns the unique identifier for the associated thread. - /// + /// Returns the unique identifier for the associated thread. public int Id { get { return unchecked((int)_threadInfo._threadId); } } - /// - /// Returns or sets whether this thread would like a priority boost if the user interacts - /// with user interface associated with this thread. - /// + /// + /// Returns or sets whether this thread would like a priority boost if the user interacts + /// with user interface associated with this thread. + /// public bool PriorityBoostEnabled { get @@ -81,11 +73,11 @@ public bool PriorityBoostEnabled } } - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// + /// + /// Returns or sets the priority level of the associated thread. The priority level is + /// not an absolute level, but instead contributes to the actual thread priority by + /// considering the priority class of the process. + /// public ThreadPriorityLevel PriorityLevel { [SupportedOSPlatform("windows")] @@ -107,26 +99,19 @@ public ThreadPriorityLevel PriorityLevel } } - /// - /// Returns the memory address of the function that was called when the associated - /// thread was started. - /// + /// Returns the memory address of the function that was called when the associated thread was started. public IntPtr StartAddress { get { return _threadInfo._startAddress; } } - /// - /// Returns the current state of the associated thread, e.g. is it running, waiting, etc. - /// + /// Returns the current state of the associated thread, e.g. is it running, waiting, etc. public ThreadState ThreadState { get { return _threadInfo._threadState; } } - /// - /// Returns the reason the associated thread is waiting, if any. - /// + /// Returns the reason the associated thread is waiting, if any. public ThreadWaitReason WaitReason { get @@ -147,9 +132,53 @@ public DateTime StartTime get => GetStartTime(); } - /// - /// Helper to check preconditions for property access. - /// + /// Sets the processor that this thread would ideally like to run on. + public int IdealProcessor { set { SetIdealProcessor(value); } } + + /// + /// Resets the ideal processor so there is no ideal processor for this thread (e.g. + /// any processor is ideal). + /// + public void ResetIdealProcessor() => ResetIdealProcessorCore(); + + /// + /// Sets which processors the associated thread is allowed to be scheduled to run on. + /// Each processor is represented as a bit: bit 0 is processor one, bit 1 is processor + /// two, etc. For example, the value 1 means run on processor one, 2 means run on + /// processor two, 3 means run on processor one or two. + /// + [SupportedOSPlatform("windows")] + public IntPtr ProcessorAffinity { set { SetProcessorAffinity(value); } } + + /// + /// Returns the amount of time the thread has spent running code inside the operating + /// system core. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public TimeSpan PrivilegedProcessorTime => GetPrivilegedProcessorTime(); + + /// + /// Returns the amount of time the associated thread has spent utilizing the CPU. + /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and + /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public TimeSpan TotalProcessorTime => GetTotalProcessorTime(); + + /// + /// Returns the amount of time the associated thread has spent running code + /// inside the application (not the operating system core). + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public TimeSpan UserProcessorTime => GetUserProcessorTime(); + + /// Helper to check preconditions for property access. private void EnsureState(State state) { if (((state & State.IsLocal) != (State)0) && _isRemoteMachine) @@ -158,10 +187,7 @@ private void EnsureState(State state) } } - /// - /// Preconditions for accessing properties. - /// - /// + /// Preconditions for accessing properties. private enum State { IsLocal = 0x2 diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs index cbffba69569a6a..63482adb0d7fdc 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs @@ -7,53 +7,18 @@ namespace System.Diagnostics { public partial class ProcessThread { - /// - /// Returns or sets the priority level of the associated thread. The priority level is - /// not an absolute level, but instead contributes to the actual thread priority by - /// considering the priority class of the process. - /// private static ThreadPriorityLevel PriorityLevelCore { get { throw new PlatformNotSupportedException(); } set { throw new PlatformNotSupportedException(); } } - /// - /// Returns the amount of time the thread has spent running code inside the operating - /// system core. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan PrivilegedProcessorTime - { - get { throw new PlatformNotSupportedException(); } - } + private static TimeSpan GetPrivilegedProcessorTime() => throw new PlatformNotSupportedException(); private static DateTime GetStartTime() => throw new PlatformNotSupportedException(); - /// - /// Returns the amount of time the associated thread has spent utilizing the CPU. - /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and - /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan TotalProcessorTime - { - get { throw new PlatformNotSupportedException(); } - } - /// - /// Returns the amount of time the associated thread has spent running code - /// inside the application (not the operating system core). - /// - [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] - [SupportedOSPlatform("maccatalyst")] - public TimeSpan UserProcessorTime - { - get { throw new PlatformNotSupportedException(); } - } + private static TimeSpan GetTotalProcessorTime() => throw new PlatformNotSupportedException(); + + private static TimeSpan GetUserProcessorTime() => throw new PlatformNotSupportedException(); } }