.NET Async Support

Requirements: Async operations are supported in all .NET editions of all toolkits.


.NET Async Libraries

Version 2022 introduces a new async version of the API designed to support asynchronous programming (async/await) for all operations. As a result, the .NET Edition includes several libraries (.dll files) for each toolkit which are supported in different environments. For example, the following IPWorks libraries are present in the lib directory after installation:

Library Supported Runtimes Comments
lib\nsoftware.IPWorks.dll .NET Framework 4.0 and up
.NET Core 3.0 and up
.NET 5 and up
This is the default library which maintains a familiar API in line with previous versions of the product. Support for asynchronous programming patterns (async/await) is exposed in a separate nsoftware.async.IPWorks namespace.
lib\netstandard2.0\nsoftware.IPWorks.dll .NET Standard 2.0 and up The .NET Standard library provides cross-platform support while maintaining the same API as the default library in lib.
lib\net20\nsoftware.IPWorks.dll .NET Framework 2.0 and up This library targets .NET Framework 2.0 and is maintained for legacy projects.

Cross-Platform Development

The async API can be used for cross-platform development on Windows, Linux and macOS, and supports the following runtime environments:

  • .NET 5 and up
  • .NET Framework 4.5 and up
  • .NET Core 3.0 and up

Refer to the cross-platform async demos included with the toolkit for more detailed examples.

Asynchronous Programming

An async version of the API designed to support asynchronous programming (async/await) is available in the nsoftware.async.IPWorks namespace. Both the default (sync) and the async APIs are present in the same library located in the installation directory at lib\nsoftware.IPWorks.dll.

The async version of the API is designed to support asynchronous programming (async/await) for all operations. In addition, the async API delivers performance improvements for these operations compared to the default version of the API. In Visual Studio's intellisense you will see methods which are awaitable and return a System.Threading.Tasks.Task object.

The async/await pattern provides a simple way to write sequential code that is easy to understand but also takes advantage of the inherent benefits of asynchronous programming. A common example of this is awaiting an asynchronous task which will wait for the operation to complete but also ensure the UI of an application is responsive and does not appear frozen.

All versions of the API use non-blocking sockets internally, the async functionality provided in this version of the API is related only to the .NET asynchronous programming model.

Error Handling

Exceptions can be handled using try/catch when awaiting a method. The behavior when using await is the same as when handling exceptions in the synchronous version of the API. There are no special requirements and the exception will contain the same Code and Message property values as the other versions of this library.

If the await keyword is not used, then the exception can be obtained from the task's Exception.InnerException property.


The InvokeThrough property is an optional property which specifies a SynchronizationContext to be used when firing events. When set, the component will fire events within the specified context. A common use case is updating Windows Forms UI elements from within an event of the component. In order to ensure that the UI update does not result in an invalid cross-thread operation set InvokeThrough to a valid value. For instance:

component.InvokeThrough = WindowsFormsSynchronizationContext.Current;

This property is applicable in any project type and may be set to any valid SynchronizationContext such as System.Threading.SynchronizationContext.Current.

The default value is null and no synchronization context will be used.

Note: Use of this property can impact performance and should only be used when necessary.

Concurrency Notes

While the asynchronous methods of the components do return a Task object only one operation can be in progress at any given time. There is no locking mechanism and it is generally considered to be dangerous to create two active tasks which use the same component instance. If multiple concurrent operations are required then multiple component instances should be used.

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.