From f168728595de3bd411aa22c3f03ae0e04320cc60 Mon Sep 17 00:00:00 2001 From: Robin Putzar Date: Thu, 25 Apr 2024 10:55:08 +0200 Subject: [PATCH 1/2] Improve compatibility with .NET Core and later (includes .NET 5 and above) --- src/HidLibrary/HidAsyncState.cs | 6 +++ src/HidLibrary/HidDevice.cs | 57 +++++++++++++++++++++++------ src/HidLibrary/HidFastReadDevice.cs | 24 +++++++++--- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/HidLibrary/HidAsyncState.cs b/src/HidLibrary/HidAsyncState.cs index c7379e9..0bf889e 100644 --- a/src/HidLibrary/HidAsyncState.cs +++ b/src/HidLibrary/HidAsyncState.cs @@ -1,5 +1,10 @@ namespace HidLibrary { +#if !NETCOREAPP1_0_OR_GREATER + // data provided to delegate BeginInvoke callbacks + // no longer needed for .NET Core and later (includes .NET 5 and above) since BeginInvoke and EndInvoke delegate + // calls are not supported, and Task<> is used instead + public class HidAsyncState { private readonly object _callerDelegate; @@ -14,4 +19,5 @@ public HidAsyncState(object callerDelegate, object callbackDelegate) public object CallerDelegate { get { return _callerDelegate; } } public object CallbackDelegate { get { return _callbackDelegate; } } } +#endif } diff --git a/src/HidLibrary/HidDevice.cs b/src/HidLibrary/HidDevice.cs index 03299ff..91cf14e 100644 --- a/src/HidLibrary/HidDevice.cs +++ b/src/HidLibrary/HidDevice.cs @@ -146,17 +146,26 @@ public void Read(ReadCallback callback) public void Read(ReadCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with Read() and call callback afterwards + Task readTask = Task.Run(() => Read(timeout)); + readTask.ContinueWith(task => callback.Invoke(task.Result)); +#else + // Note: delegate BeginInvoke calls are not supported in .NET Core and later (includes .NET 5 and above), + // see e.g. https://devblogs.microsoft.com/dotnet/migrating-delegate-begininvoke-calls-for-net-core/ + var readDelegate = new ReadDelegate(Read); var asyncState = new HidAsyncState(readDelegate, callback); readDelegate.BeginInvoke(timeout, EndRead, asyncState); +#endif } public async Task ReadAsync(int timeout = 0) { - var readDelegate = new ReadDelegate(Read); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => readDelegate.Invoke(timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => Read(timeout)); #else + var readDelegate = new ReadDelegate(Read); return await Task.Factory.FromAsync(readDelegate.BeginInvoke, readDelegate.EndInvoke, timeout, null); #endif } @@ -178,17 +187,23 @@ public void ReadReport(ReadReportCallback callback) public void ReadReport(ReadReportCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with ReadReport() and call callback afterwards + Task readReportTask = Task.Run(() => ReadReport(timeout)); + readReportTask.ContinueWith(task => callback.Invoke(task.Result)); +#else var readReportDelegate = new ReadReportDelegate(ReadReport); var asyncState = new HidAsyncState(readReportDelegate, callback); readReportDelegate.BeginInvoke(timeout, EndReadReport, asyncState); +#endif } public async Task ReadReportAsync(int timeout = 0) { - var readReportDelegate = new ReadReportDelegate(ReadReport); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => readReportDelegate.Invoke(timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => ReadReport(timeout)); #else + var readReportDelegate = new ReadReportDelegate(ReadReport); return await Task.Factory.FromAsync(readReportDelegate.BeginInvoke, readReportDelegate.EndInvoke, timeout, null); #endif } @@ -361,17 +376,23 @@ public void Write(byte[] data, WriteCallback callback) public void Write(byte[] data, WriteCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with Write() and call callback afterwards + Task writeTask = Task.Run(() => Write(data, timeout)); + writeTask.ContinueWith(task => callback.Invoke(task.Result)); +#else var writeDelegate = new WriteDelegate(Write); var asyncState = new HidAsyncState(writeDelegate, callback); writeDelegate.BeginInvoke(data, timeout, EndWrite, asyncState); +#endif } public async Task WriteAsync(byte[] data, int timeout = 0) { - var writeDelegate = new WriteDelegate(Write); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => writeDelegate.Invoke(data, timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => Write(data, timeout)); #else + var writeDelegate = new WriteDelegate(Write); return await Task.Factory.FromAsync(writeDelegate.BeginInvoke, writeDelegate.EndInvoke, data, timeout, null); #endif } @@ -393,9 +414,15 @@ public void WriteReport(HidReport report, WriteCallback callback) public void WriteReport(HidReport report, WriteCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with WriteReport() and call callback afterwards + Task writeReportTask = Task.Run(() => WriteReport(report, timeout)); + writeReportTask.ContinueWith(task => callback.Invoke(task.Result)); +#else var writeReportDelegate = new WriteReportDelegate(WriteReport); var asyncState = new HidAsyncState(writeReportDelegate, callback); writeReportDelegate.BeginInvoke(report, timeout, EndWriteReport, asyncState); +#endif } /// @@ -419,10 +446,10 @@ public bool WriteReportSync(HidReport report) public async Task WriteReportAsync(HidReport report, int timeout = 0) { - var writeReportDelegate = new WriteReportDelegate(WriteReport); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => writeReportDelegate.Invoke(report, timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => WriteReport(report, timeout)); #else + var writeReportDelegate = new WriteReportDelegate(WriteReport); return await Task.Factory.FromAsync(writeReportDelegate.BeginInvoke, writeReportDelegate.EndInvoke, report, timeout, null); #endif } @@ -465,6 +492,11 @@ public bool WriteFeatureData(byte[] data) return success; } +#if !NETCOREAPP1_0_OR_GREATER + // callbacks provided to delegate BeginInvoke + // no longer needed for .NET Core and later (includes .NET 5 and above) since BeginInvoke and EndInvoke + // delegate calls are not supported, and Task<> is used instead + protected static void EndRead(IAsyncResult ar) { var hidAsyncState = (HidAsyncState)ar.AsyncState; @@ -504,6 +536,7 @@ private static void EndWriteReport(IAsyncResult ar) if ((callbackDelegate != null)) callbackDelegate.Invoke(result); } +#endif private byte[] CreateInputBuffer() { diff --git a/src/HidLibrary/HidFastReadDevice.cs b/src/HidLibrary/HidFastReadDevice.cs index 8f384d6..f7d6b22 100644 --- a/src/HidLibrary/HidFastReadDevice.cs +++ b/src/HidLibrary/HidFastReadDevice.cs @@ -34,17 +34,23 @@ public void FastRead(ReadCallback callback) public void FastRead(ReadCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with FastRead() and call callback afterwards + Task readTask = Task.Run(() => FastRead(timeout)); + readTask.ContinueWith(task => callback.Invoke(task.Result)); +#else var readDelegate = new ReadDelegate(FastRead); var asyncState = new HidAsyncState(readDelegate, callback); readDelegate.BeginInvoke(timeout, EndRead, asyncState); +#endif } public async Task FastReadAsync(int timeout = 0) { - var readDelegate = new ReadDelegate(FastRead); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => readDelegate.Invoke(timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => FastRead(timeout)); #else + var readDelegate = new ReadDelegate(FastRead); return await Task.Factory.FromAsync(readDelegate.BeginInvoke, readDelegate.EndInvoke, timeout, null); #endif } @@ -66,17 +72,23 @@ public void FastReadReport(ReadReportCallback callback) public void FastReadReport(ReadReportCallback callback, int timeout) { +#if NETCOREAPP1_0_OR_GREATER + // start new task with FastReadReport() and call callback afterwards + Task readReportTask = Task.Run(() => FastReadReport(timeout)); + readReportTask.ContinueWith(task => callback.Invoke(task.Result)); +#else var readReportDelegate = new ReadReportDelegate(FastReadReport); var asyncState = new HidAsyncState(readReportDelegate, callback); readReportDelegate.BeginInvoke(timeout, EndReadReport, asyncState); +#endif } public async Task FastReadReportAsync(int timeout = 0) { - var readReportDelegate = new ReadReportDelegate(FastReadReport); -#if NET20 || NET35 || NET5_0_OR_GREATER - return await Task.Factory.StartNew(() => readReportDelegate.Invoke(timeout)); +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER + return await Task.Factory.StartNew(() => FastReadReport(timeout)); #else + var readReportDelegate = new ReadReportDelegate(FastReadReport); return await Task.Factory.FromAsync(readReportDelegate.BeginInvoke, readReportDelegate.EndInvoke, timeout, null); #endif } From a7ac8572daf3445377a9bb6f2e7b3829690454b6 Mon Sep 17 00:00:00 2001 From: Robin Putzar Date: Thu, 25 Apr 2024 11:37:34 +0200 Subject: [PATCH 2/2] modified #if in HidDeviceEventMonitor.cs to concur with previous changes --- src/HidLibrary/HidDeviceEventMonitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HidLibrary/HidDeviceEventMonitor.cs b/src/HidLibrary/HidDeviceEventMonitor.cs index ada9df1..53b654f 100644 --- a/src/HidLibrary/HidDeviceEventMonitor.cs +++ b/src/HidLibrary/HidDeviceEventMonitor.cs @@ -22,7 +22,7 @@ public HidDeviceEventMonitor(HidDevice device) public void Init() { -#if NET20 || NET35 || NET5_0_OR_GREATER +#if NET20 || NET35 || NETCOREAPP1_0_OR_GREATER Task task = Task.Factory.StartNew(() => DeviceEventMonitor()); #else var eventMonitor = new Action(DeviceEventMonitor);