Many Ignite APIs have asynchronous variants, for example,
void ICache.Put and
Async APIs allow us to write efficient non-blocking code:
ICache<int, string> cache = ignite.GetOrCreateCache<int, string>("name"); // Sync, blocks thread on every call. cache.Put(1, "Hello"); string hello = cache.Get(1); // Async, does not block threads. await cache.PutAsync(1, "Hello"); string hello = await cache.GetAsync(1);
With async APIs, current thread is not blocked while we wait for the cache operation to complete; the thread is returned to the thread pool and can perform other work.
When the async operation completes, our method resumes execution - either on the same thread, or on a different one - depending on the environment and the configuration. This is called "async continuation".
Unless specified otherwise, Ignite executes async continuations on the .NET Thread Pool, which is safe and does not require any special care.
All thin client async APIs use .NET Thread Pool. for async continuations.
Callbacks for asynchronous cache operations on server and thick client nodes are invoked by using Java
ForkJoinPool#commonPool, unless a different executor is configured with
This default executor is safe for any operations inside the callback.
Default behavior was changed in Ignite 2.11. Before that, async cache operation callbacks were called from an Ignite system pool (so-called "striped pool").
To restore the previous behavior, use
IgniteConfiguration.AsyncContinuationExecutor = AsyncContinuationExecutor.UnsafeSynchronous.
Previous behavior can provide a small performance improvement, because callbacks are executed without any indirection or scheduling.
UNSAFE: cache operations cannot proceed while system threads execute callbacks, and deadlocks are possible if other cache operations are invoked from the callback.
Ignite 2.10 and before: possibility of deadlocks and system pool starvation
In Ignite versions 2.10 and before, system pool is used to run async continuations,
which means that
This can lead to deadlocks if user code blocks the thread, or cause starvation because system thread is busy running user code instead of performing cache operations.
To enable safe behavior, move continuations to .NET Thread Pool manually:
Tip: use an extension method to reduce verbosity.
Ignite 2.11 and later: all
ICompute async APIs use .NET Thread Pool to run async continuations.
Ignite 2.10 and before: Compute async continuations are executed on Ignite public pool.
To reduce the load on the public pool, it is recommended to use the same
ContinueWith approach as above:
await compute.CallAsync(new MyAction()).ContinueWith( t => t.Result, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
This will move the continuation from Ignite public pool (reserved for Compute functionality) to the .NET thread pool (
Task.ConfigureAwait method can be used as usual with all Ignite async APIs.
See ConfigureAwait FAQ for more details.
Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are either registered trademarks or trademarks of The Apache Software Foundation.