Call model
Every extension is called by the platform, never the other way round, and every kind is called by its own host: the chart, the heatmap, the SmartDOM, the Watchlist, a module panel, the connection manager. This page puts the rules of all the kinds side by side: who calls your code and when, on which thread, how long a call may take, and what happens when it throws. The articles of the kinds describe the details; read the one of your kind before you rely on this summary.
The two models
The kinds fall into two groups.
Chart indicators and chart strategies are called directly from the threads where things happen: the calculation
from the data threads, the drawing from the drawing thread, the trading events from the trading connection. Only
OnCalculate is protected from itself; everything else may run at the same time as the calculation, and you share
data between the threads yourself. An exception is logged and the indicator stays on the chart.
Heatmap indicators, SmartDOM and Watchlist columns and custom modules run behind an adapter: the platform copies the data, delivers it on a thread of its own and never calls one instance concurrently, so their fields need no locks. In return a call has a time budget, and an exception, or calls that are slow again and again, stop the instance.
Connectors are a third case: they feed the platform rather than read from it, and they own a processing queue of their own.
Summary
| Kind | Calls | Thread | Concurrent calls | Time limit | When your code throws |
|---|---|---|---|---|---|
| Chart indicator | OnCalculate for the history and every tick; market data and trading callbacks; OnRender; the timer |
Data threads, the drawing thread, background threads | Yes, except OnCalculate with itself |
None; live calls for the same bar are skipped when the calculation is slow | Logged (OnCalculate and OnRender at most once per 10 s per instance); the indicator keeps running |
| Chart strategy | As an indicator, plus OnStarted, OnStopping, OnStopped, the order events |
As an indicator | As an indicator | None | Logged; see the warning below |
| Heatmap indicator | ConfigureAsync, ProcessTicksAsync, ProcessProfileAsync, ProcessMboAsync, the timer, warm-up and reset |
The instance's own background task | No, except GetRequiredProfilePeriods |
2 s per call, 30 s for WarmUpAsync, through the cancellation token |
The indicator is stopped; so are 3 timeouts within 30 s |
| SmartDOM column | Data callbacks, OnTimer about 10 times a second, OnDrawCell, clicks, OnSettingsChanged |
Data on a background thread, drawing on the drawing thread | No | 100 ms per call; 5 slow calls within 10 s stop the column | The instance is released (OnDispose), the header shows «Error» |
| Watchlist column | Data callbacks, OnTimer about once a second, OnSettingsChanged |
A background thread, within about 0.1 s of the data | No; all rows of a column share one lock | 100 ms per call; 5 slow calls within 10 s stop the column | The whole column is stopped, every row; the header shows «Error» |
| Custom module | Constructor and OnInitialize, data callbacks, OnTimer about 10 times a second, OnRender, input, header buttons |
Data, constructor and OnInitialize on a background thread; drawing and input on the thread of the panel |
No | 100 ms per call; 5 slow calls within 10 s stop the module | The module is stopped, the panel shows «Error» |
| Connector | OnConnect, OnDisconnect, OnSearchSecurities, the subscription methods, OnProcess |
OnConnect and OnDisconnect on the thread pool, searches and subscriptions on the caller's thread (possibly the UI thread), processing on the connector's queue thread |
Yes; serialize through the queue | OnConnected within ConnectTimeout (60 s by default) |
In OnConnect: the attempt fails and is not retried; in OnProcess or a queued action: logged, the queue continues |
Rules for every kind
- Construct cheaply, start late. The constructor of every kind runs before the extension is attached to its
host, often on a background thread, and again whenever the host recreates it (a chart reload, a template, a changed
layout). Create fields and defaults there; start subscriptions, timers and tasks in
OnInitialize(orOnConnectfor a connector). - Release what you started. Every kind has a place where the platform says goodbye:
OnDisposefor indicators, columns and modules,OnStoppingandOnStoppedfor strategies,OnDisconnectfor connectors. The platform releases its own subscriptions (timers, candle series, options, other instruments); tasks, event handlers and native resources of your own are yours. - Never block a callback. A call that waits for the network, a file or a lock held elsewhere stalls the thread it runs on: the chart's data, the drawing of a panel, the queue of a connector. Start a task and give its result to the next call.
- UI work goes through the host. A chart indicator uses
DoActionInGuiThread; SmartDOM columns and modules draw inOnDrawCellorOnRenderand ask for a frame withRedraw(); a Watchlist column sets the values of its cells; a heatmap indicator writes its visual state and the heatmap draws it. Do not touch WPF or Avalonia objects from your own threads. - Exceptions are not control flow. For the adapter kinds an exception ends the instance; for chart indicators it loses the data of the call. Check the inputs and catch what you expect.
Warning
Chart strategies: an exception in OnStopping leaves the strategy started. The platform calls OnStopping
before it resets the strategy; when OnStopping throws, the exception is logged and the reset does not happen. Catch
the exceptions of the code that closes the position and cancels the orders there. An exception in OnStarted is
logged too, and the strategy stays started.
Related articles
- Extension kinds and common rules: what each kind is for.
- Tariffs: what an extension observes when the tariff restricts it.
- Diagnostics: logs and debugging: where the logged exceptions go.