mirror of
https://github.com/freedbygrace/PSOPNSenseAPI.git
synced 2026-08-03 07:30:51 +00:00
Update Test-OPNSenseThreading cmdlet to work without connection (v2025.04.15.1749)
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Management.Automation;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using PSOPNSenseAPI.Logging;
|
||||
|
||||
namespace PSOPNSenseAPI.Cmdlets
|
||||
{
|
||||
@@ -11,7 +12,7 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// </summary>
|
||||
[Cmdlet(VerbsDiagnostic.Test, "OPNSenseThreading")]
|
||||
[OutputType(typeof(string))]
|
||||
public class TestThreadingCmdlet : OPNSenseBaseCmdlet
|
||||
public class TestThreadingCmdlet : PSCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="description">The test mode to run.</para>
|
||||
@@ -26,41 +27,101 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
[Parameter(Mandatory = false)]
|
||||
public int Delay { get; set; } = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Exception to be processed in ProcessRecord
|
||||
/// </summary>
|
||||
protected Exception ProcessingException { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Begins the processing of the cmdlet
|
||||
/// </summary>
|
||||
protected override void BeginProcessing()
|
||||
{
|
||||
base.BeginProcessing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecordInternal()
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
WriteVerbose($"Starting test in mode: {Mode}");
|
||||
WriteVerbose($"Current thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteVerbose($"Current synchronization context: {SynchronizationContext.Current != null}");
|
||||
|
||||
switch (Mode)
|
||||
try
|
||||
{
|
||||
case "Direct":
|
||||
TestDirect();
|
||||
break;
|
||||
case "ConfigureAwait":
|
||||
TestConfigureAwait();
|
||||
break;
|
||||
case "SynchronizationContext":
|
||||
TestSynchronizationContext();
|
||||
break;
|
||||
case "TaskRun":
|
||||
TestTaskRun();
|
||||
break;
|
||||
}
|
||||
WriteVerbose($"Starting test in mode: {Mode}");
|
||||
WriteVerbose($"Current thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteVerbose($"Current synchronization context: {SynchronizationContext.Current != null}");
|
||||
|
||||
WriteVerbose("Test completed");
|
||||
switch (Mode)
|
||||
{
|
||||
case "Direct":
|
||||
TestDirect();
|
||||
break;
|
||||
case "ConfigureAwait":
|
||||
TestConfigureAwait();
|
||||
break;
|
||||
case "SynchronizationContext":
|
||||
TestSynchronizationContext();
|
||||
break;
|
||||
case "TaskRun":
|
||||
TestTaskRun();
|
||||
break;
|
||||
}
|
||||
|
||||
WriteVerbose("Test completed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteWarning($"Error occurred: {ex.Message}");
|
||||
ProcessingException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Process any exceptions that occurred
|
||||
if (ProcessingException != null)
|
||||
{
|
||||
WriteWarning($"Processing exception: {ProcessingException.Message}");
|
||||
ProcessingException = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends the processing of the cmdlet
|
||||
/// </summary>
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
base.EndProcessing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes an async task synchronously and safely
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The return type of the task</typeparam>
|
||||
/// <param name="asyncFunc">The async function to execute</param>
|
||||
/// <returns>The result of the async function</returns>
|
||||
protected T ExecuteAsyncTask<T>(Func<Task<T>> asyncFunc)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Use ConfigureAwait(false) to avoid deadlocks
|
||||
return asyncFunc().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Store the exception to be processed in ProcessRecord
|
||||
ProcessingException = ex;
|
||||
WriteWarning($"Error occurred: {ex.Message}");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
private void TestDirect()
|
||||
{
|
||||
WriteVerbose("Testing direct method call");
|
||||
WriteVerbose($"Before delay - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
|
||||
|
||||
Task.Delay(Delay).Wait();
|
||||
|
||||
|
||||
WriteVerbose($"After delay - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteObject("Direct test completed");
|
||||
}
|
||||
@@ -69,13 +130,13 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
{
|
||||
WriteVerbose("Testing ConfigureAwait(false)");
|
||||
WriteVerbose($"Before async call - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
|
||||
var result = ExecuteAsyncTask(() => Task.Delay(Delay).ContinueWith(t =>
|
||||
|
||||
var result = ExecuteAsyncTask(() => Task.Delay(Delay).ContinueWith(t =>
|
||||
{
|
||||
WriteVerbose($"Inside async task - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
return "ConfigureAwait test completed";
|
||||
}));
|
||||
|
||||
|
||||
WriteVerbose($"After async call - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteObject(result);
|
||||
}
|
||||
@@ -85,24 +146,24 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
WriteVerbose("Testing SynchronizationContext");
|
||||
WriteVerbose($"Before async call - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteVerbose($"SynchronizationContext: {SynchronizationContext.Current != null}");
|
||||
|
||||
|
||||
var syncContext = SynchronizationContext.Current;
|
||||
var result = ExecuteAsyncTask(() => Task.Delay(Delay).ContinueWith(t =>
|
||||
var result = ExecuteAsyncTask(() => Task.Delay(Delay).ContinueWith(t =>
|
||||
{
|
||||
var taskThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||
WriteVerbose($"Inside async task - Thread ID: {taskThreadId}");
|
||||
|
||||
|
||||
if (syncContext != null)
|
||||
{
|
||||
syncContext.Post(_ =>
|
||||
syncContext.Post(_ =>
|
||||
{
|
||||
WriteVerbose($"Inside SynchronizationContext.Post - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
}, null);
|
||||
}
|
||||
|
||||
|
||||
return "SynchronizationContext test completed";
|
||||
}));
|
||||
|
||||
|
||||
WriteVerbose($"After async call - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteObject(result);
|
||||
}
|
||||
@@ -111,17 +172,17 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
{
|
||||
WriteVerbose("Testing Task.Run");
|
||||
WriteVerbose($"Before Task.Run - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
|
||||
var task = Task.Run(() =>
|
||||
|
||||
var task = Task.Run(() =>
|
||||
{
|
||||
WriteVerbose($"Inside Task.Run - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
Thread.Sleep(Delay);
|
||||
WriteVerbose($"After delay in Task.Run - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
return "TaskRun test completed";
|
||||
});
|
||||
|
||||
|
||||
var result = task.GetAwaiter().GetResult();
|
||||
|
||||
|
||||
WriteVerbose($"After Task.Run - Thread ID: {Thread.CurrentThread.ManagedThreadId}");
|
||||
WriteObject(result);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
RootModule = 'lib\PSOPNSenseAPI.dll'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '2025.04.15.1740'
|
||||
ModuleVersion = '2025.04.15.1749'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = @('Desktop', 'Core')
|
||||
|
||||
Reference in New Issue
Block a user