Skip to content

Async and cancellation

Daniel Frantík edited this page Oct 15, 2026 · 1 revision

Async and cancellation

The awaitable side of tik4net: every command and every O/R-mapper call has a …Async form that takes a CancellationToken and occupies no thread while the router works. Use it in services, UIs and anywhere a blocked thread costs you. The rules are those of the synchronous calls — only the waiting changes.

using tik4net;
using tik4net.Objects;
using tik4net.Objects.Ip;

using ITikConnection connection = await setup.CreateAsync(TikConnectionType.Api, cancellationToken);

string identity = await connection.CreateCommand("/system/identity/print").ExecuteScalarAsync(cancellationToken);

var address = await connection.LoadByIdAsync<IpAddress>("*1", cancellationToken);
address.Comment = "WAN";
await connection.SaveAsync(address, cancellationToken: cancellationToken);

Not to be confused with callbacks. ExecuteWithCallback / LoadWithCallback / LoadListenWithCallback start a command that keeps running and hand you rows as they come; they return a running ITikCommand, not a Task. They are on Monitors and streaming.

The async methods

Level Synchronous Async
Opening setup.Create, setup.CreateApiConnection, … CreateAsync, CreateApiConnectionAsync, …
Low level CallCommandSync CallCommandAsync
ADO.NET-like ExecuteNonQuery, ExecuteScalar, ExecuteScalarOrDefault, ExecuteSingleRow, ExecuteSingleRowOrDefault, ExecuteList the same names + Async
O/R mapper — read LoadAll, LoadList, LoadSingle, LoadSingleOrDefault, LoadById, LoadByName the same names + Async
O/R mapper — write Save, Delete, DeleteAll, SaveListDifferences, Move, MoveToEnd the same names + Async
List merge merge.Save() merge.SaveAsync()
Streaming (net8.0) ExecuteListWithDuration, ExecuteListUntilDone …Async as IAsyncEnumerable — see Monitors and streaming
  • They are extension methods — using tik4net; for commands, using tik4net.Objects; for entities.
  • They throw what the synchronous form throws, plus OperationCanceledException when the token fires (never wrapped in a Tik* exception).
  • LoadListAsync / LoadSingleAsync take the token before the filter parameters:
var wan = await connection.LoadListAsync<IpAddress>(cancellationToken,
    connection.CreateParameter("interface", "ether1"));
  • SaveAsync has the optional usedFieldsFilter and saveMode of Save, so pass the token by name.
  • A list save (SaveListDifferencesAsync, merge.SaveAsync) is several commands with no transaction: the token is checked between them, and the ones already sent stay applied. Reload and run it again to finish.
  • LoadWithDuration has no async form.

Which transports

All shipped transports declare AsyncCommands. A custom ITikConnection that does not throws TikConnectionCapabilityNotSupportedException instead of blocking a thread-pool thread:

var rows = connection.Supports(TikConnectionCapability.AsyncCommands)
    ? await cmd.ExecuteListAsync(cancellationToken)
    : cmd.ExecuteList().ToList();

What the CancellationToken does

You cancel… Result
before the command is sent nothing is sent; OperationCanceledException; the connection is untouched — every transport
after it is sent, transport has CancelInFlight the wait ends at once and the connection stays usable
after it is sent, no CancelInFlight the reply is read to its end first, then OperationCanceledException
Transport CancelInFlight What a cancel after sending does
Api, ApiSsl ✅ sends /cancel — the router stops the command
Rest, RestSsl ✅ aborts the HTTP request — you stop waiting, but the router finishes the command
WinboxNative, WinboxNativeMac ✅ a streaming window (torch, ping, scan, …) is stopped on the router; an ordinary call is finished by the router and its late reply discarded
CLI transports — waits for the reply to end — a terminal has no way to skip an unfinished reply without the next command reading it

Trading the connection for a prompt return

On the CLI transports you can choose to lose the connection rather than wait. It is a connection setting, not a per-call one:

using tik4net.Telnet;

var setup = new TikConnectionSetup(HOST, USER, PASS)
{
    CancellationMode = TikCancellationMode.AbandonAndClose,   // default: Cooperative
};
using var connection = setup.CreateTelnetConnection();
CancellationMode A token cancelled after sending
Cooperative (default) the reply is drained, then OperationCanceledException; the connection stays usable
AbandonAndClose the read is cut and the connection is closed — the next command throws TikConnectionNotOpenException

Transports with CancelInFlight ignore the setting.

Opening

CreateAsync and the Create…ConnectionAsync factories accept a token too; how far into the open it reaches depends on the transport — see Connecting to a router.

Testing code that awaits

TikFakeConnection supports the async surface; its commands complete synchronously. Remove AsyncCommands from its Capabilities to exercise your fallback path.

See also

Clone this wiki locally