Песочница
Песочница скрипта
Песочница это штука, в которой запускаются ваши скрипты. Она предоставляет объект host/globals с базовыми методами и свойствами. В Script.csx они доступны напрямую; обычные C# классы их не наследуют и должны получать зависимости явно.
Зачем она нужна?
Хранит в себе состояние между запусками
Когда вы создаете какое-то свойство или службу, отрисовываете картинку на экране или распознаете текст, то во избежание многократного создания одного и того же, песочница сохраняет и переиспользует данные от предыдущих запусков. Это увеличивает производительность и делает написание скриптов более простым
Подчищает за скриптом мусор
Ресурсы одного запуска можно привязать к ExecutionAnchors: они освобождаются при выходе из Run. Сама песочница и её Anchors могут жить дольше и переиспользоваться. Созданные вами подписки и другие ресурсы требуют явного управления временем жизни; не каждый результат GetService автоматически освобождается за вас.

Предоставляет набор базового функционала
Чтобы было проще жить, в абсолютно любом скрипте по умолчанию присутствует набор неких базовых сервисов - возможность писать логи, возможность работы с файлами программы и т.п. Однако, во избежание накопления лишнего веса, этот функционал очень и очень ограничен. Предполагается, что пользователь пользуется методом GetService<> чтобы добавить скрипту любые нужные ему возможности. Об этом чуть ниже
Что там по коду
Давайте рассмотрим методы и свойства, которые есть у абсолютно любого скрипта
Логгирование
IFluentLog Log { get; }
Почти любому скрипту на одном из этапов жизни нужно давать какую-то обратную связь - текущие значения переменных, отладочные сообщения и т.п.
Log отвечает именно за это. С его помощью можно писать сообщения как в файлы логов программы, так и в окошко Event Log.
У каждой строчки лога есть один из уровней: Debug, Info, Warn, Error
Чем выше уровень - тем важнее сообщение, Error самые важные. В Event Log вы можете регулировать от какого уровня показывать сообщения. По умолчанию от Info и выше
Log.Info("Hello!");
Log.Debug("Hello from debug level!");

Любителям поспать
void Sleep(TimeSpan delay);
void Sleep(int delayMs)
Этот метод приостанавливает выполнение скрипта на указанное время. Он использует текущий cancellationToken. Это синхронная пауза; для асинхронного ожидания используйте await Task.Delay(..., token).
Sleep(2000); //приостанавливаем скрипт на 2 секунды
Sleep(TimeSpan.FromMilliseconds(100)); //приостанавливаем на 100 миллисекунд
Если по какой-то причине программа попросит скрипт остановиться (к примеру, ауру со скриптом выгрузили), то
Sleepпрервется заранее и скрипт будет остановлен

Dependency Injection
T GetService<T>()
Самый могучий метод в песочнице. Это связь вашего скрипта с внешним миром и возможность получить доступ к разным частям функционала программы.
Используя GetService вы можете запросить у программы ниточки, дергая за которые будете получать тот или иной эффект.
Вместо тысячи слов:
Например, передадим логгер обычному классу. В Script.csx:
var reporter = new Reporter(Log);
reporter.Report(2 + 3);
В отдельном Reporter.cs:
using PoeShared.Logging;
public sealed class Reporter
{
private readonly IFluentLog log;
public Reporter(IFluentLog log) => this.log = log;
public void Report(int value) => log.Info($"Result: {value}");
}
В Event Log появится Result: 5. Для получения зарегистрированной службы используйте её точный интерфейс и namespace; наличие типа в SDK ещё не гарантирует регистрацию. Свои службы можно добавить через Script Container Extensions.
Выполнить работу с отменой одного запуска
Код для Script.csx:
using System.Threading.Tasks;
var runToken = cancellationToken;
for (var step = 1; step <= 3; step++)
{
runToken.ThrowIfCancellationRequested();
Log.Info($"Step {step}");
await Task.Delay(500, runToken);
}
Скрипт пишет три сообщения с паузами. Если host отменит запуск, ожидание прервётся отменой. cancellationToken и ExecutionAnchors назначаются для каждого Run, а после него сбрасываются. Захватите токен и передайте его в выполняемую работу; не храните его как постоянный токен всей песочницы и не оставляйте неотслеживаемые фоновые задачи после выхода.
Состояние объекта скрипта может сохраняться при повторных запусках с той же версией проекта. Изменение зависимой версии проекта пересоздаёт контекст; это не долговременное хранилище. Для обмена данными и настроек смотрите переменные, для ресурсов — управление временем жизни.