4 Commits

4 changed files with 40 additions and 12 deletions

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Runtime.InteropServices;
namespace Nefarius.Peripherals.SerialPort; namespace Nefarius.Peripherals.SerialPort;
@ -22,4 +23,14 @@ public class CommPortException : ApplicationException
public CommPortException(Exception e) : base("Receive Thread Exception", e) public CommPortException(Exception e) : base("Receive Thread Exception", e)
{ {
} }
public CommPortException(string message, int error) : base(message)
{
Win32Error = error;
}
/// <summary>
/// The Win32 error that caused the exception.
/// </summary>
public int Win32Error { get; } = Marshal.GetLastWin32Error();
} }

View File

@ -27,7 +27,9 @@
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.123"> <PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.123">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Windows.SDK.Win32Metadata" Version="61.0.15-preview" /> <PackageReference Include="Microsoft.Windows.SDK.Win32Metadata" Version="61.0.15-preview">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Memory" Version="4.5.5" /> <PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="MinVer" Version="5.0.0"> <PackageReference Include="MinVer" Version="5.0.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@ -22,6 +22,7 @@ public partial class SerialPort : IDisposable
private readonly ManualResetEvent _writeEvent = new(false); private readonly ManualResetEvent _writeEvent = new(false);
private bool _auto; private bool _auto;
private bool _checkSends = true; private bool _checkSends = true;
private CancellationTokenSource _cts;
private Handshake _handShake; private Handshake _handShake;
private SafeFileHandle _hPort; private SafeFileHandle _hPort;
@ -70,8 +71,12 @@ public partial class SerialPort : IDisposable
} }
_hPort = PInvoke.CreateFile(PortName, _hPort = PInvoke.CreateFile(PortName,
(uint)(FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE), 0, (uint)(FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE),
null, FILE_CREATION_DISPOSITION.OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED, null); 0,
null,
FILE_CREATION_DISPOSITION.OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_OVERLAPPED,
null
);
if (_hPort.IsInvalid) if (_hPort.IsInvalid)
{ {
@ -80,7 +85,7 @@ public partial class SerialPort : IDisposable
return false; return false;
} }
throw new CommPortException("Port Open Failure"); throw new CommPortException("Port Open Failure", Marshal.GetLastWin32Error());
} }
_online = true; _online = true;
@ -147,6 +152,7 @@ public partial class SerialPort : IDisposable
_rxException = null; _rxException = null;
_rxExceptionReported = false; _rxExceptionReported = false;
_cts = new CancellationTokenSource();
_rxThread = new Thread(ReceiveThread) _rxThread = new Thread(ReceiveThread)
{ {
Name = "CommBaseRx", Priority = ThreadPriority.AboveNormal, IsBackground = true Name = "CommBaseRx", Priority = ThreadPriority.AboveNormal, IsBackground = true
@ -171,21 +177,25 @@ public partial class SerialPort : IDisposable
/// </summary> /// </summary>
public void Close() public void Close()
{ {
if (_online) if (!_online)
{ {
_auto = false; return;
BeforeClose(false);
InternalClose();
_rxException = null;
} }
_auto = false;
BeforeClose(false);
InternalClose();
_rxException = null;
} }
private void InternalClose() private void InternalClose()
{ {
PInvoke.CancelIo(_hPort); PInvoke.CancelIo(_hPort);
if (_rxThread != null) if (_rxThread != null)
{ {
_rxThread.Abort(); _cts.Cancel();
_rxThread.Join();
_rxThread = null; _rxThread = null;
} }
@ -399,6 +409,9 @@ public partial class SerialPort : IDisposable
{ {
} }
/// <summary>
/// Invoked when a single character has been received.
/// </summary>
public event Action<byte> DataReceived; public event Action<byte> DataReceived;
/// <summary> /// <summary>
@ -457,7 +470,7 @@ public partial class SerialPort : IDisposable
try try
{ {
while (true) while (!_cts.IsCancellationRequested)
{ {
COMM_EVENT_MASK eventMask = 0; COMM_EVENT_MASK eventMask = 0;
@ -474,7 +487,7 @@ public partial class SerialPort : IDisposable
{ {
if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING) if (Marshal.GetLastWin32Error() == (int)WIN32_ERROR.ERROR_IO_PENDING)
{ {
sg.WaitOne(); WaitHandle.WaitAny(new[] { sg, _cts.Token.WaitHandle });
} }
else else
{ {

View File

@ -20,5 +20,7 @@ internal class Program
serialPort.Write("START\r\n"); serialPort.Write("START\r\n");
Console.ReadKey(); Console.ReadKey();
serialPort.Close();
} }
} }