У меня есть служба Windows, написанная на С#, которая периодически запускает фоновые задания. Как правило, в любой момент времени параллельно работают несколько десятков сильно связанных задач ввода-вывода (загрузка больших файлов и т.д.). Служба работает на относительно занятом веб-сервере (необходимо на данный момент), и я думаю, что это может значительно помочь с точки зрения сохранения потоков для использования асинхронных API как можно больше.
Большая часть этой работы выполнена. Все задания теперь полностью асинхронны (использование HttpClient и т.д.), А также основной цикл работы (с большими дозами Task.Delay). Осталось выяснить, как правильно и безопасно запускать основной цикл из сервиса OnStart. Essentialy, это предостережение о дилемме "вызов-асинхронная синхронизация". Ниже я до сих пор (сильно упрощен).
в Program.cs:
static void Main(string[] args) {
TaskScheduler.UnobservedTaskException += (sender, e) => {
// log & alert!
e.SetObserved();
};
ServiceBase.Run(new MyService());
}
в MyService.cs:
protected override void OnStart(string[] args) {
_scheduler.StartLoopAsync(); // fire and forget! will this get me into trouble?
}
Это вызов, который вызывает StartLoopAsync
, который касается меня. Я не могу просто Wait()
вернуть возвращаемую задачу, потому что OnStart должен вернуться относительно быстро. (Петли задания должны запускаться по отдельному потоку.) Приходят в голову пару соображений:
- Я хорошо освещен до незаметных исключений, разместив этот обработчик в Main?
- Будет ли какая-либо польза от использования Task.Run, что-то вроде
Task.Run(() => _scheduler.StartLoopAsync().Wait());
? - Будет ли какая-нибудь польза для вызова
_scheduler.StartLoopAsync().ConfigureAwait(false)
здесь? (Я сомневаюсь, так как здесь нетawait
.) - Будет ли какая-либо польза от использования Stephen Cleary AsyncContextThread в этой ситуации? Я не видел никаких примеров использования этого, и поскольку я начинаю бесконечный цикл, я не знаю, что синхронизация обратно в какой-то контекст даже имеет значение здесь.