Наш сценарий
У нас размещен крупномасштабный веб-сервис WCF, который логически имеет следующий код:
Код: Выделить всё
void WcfApiMethod()
{
// logic
// invoke other tasks which are critical
var mainTask = Task.Factory.StartNew(() => { /* important task */ });
mainTask.Wait();
// invoke background task which is not critical
var backgroundTask = Task.Factory.StartNew(() => { /* some low-priority background action (not entirely async) */ });
// no need to wait, as this task is best effort. Fire and forget
// other logic
}
// other APIs
Это создает сценарий, в котором новые исполнения API не могут запланировать задачу с высоким приоритетом, поскольку в очереди находится множество фоновых задач.
Решения, которые мы опробовали
- Добавление TaskCreationOptions.LongRunning в высокопроизводительную pri задача немедленно выполнит ее.
Однако для нас это не может быть решением, так как повсюду в системе вызывается множество задач, и мы не можем сделать их везде долговыполняющимися.
Кроме того, обработка WCF входящих API будет зависеть от пула потоков .NET, который сейчас находится в нехватке. - Короткое замыкание с низкой ценой создание фоновой задачи через семафор. Создавать потоки только в том случае, если у системы есть возможность их обработать (проверьте, завершились ли ранее созданные потоки). Если нет, просто не создавайте темы.
Например, из-за проблемы (скажем, проблемы с производительностью БД) около 10 000 фоновых потоков (не асинхронных) находятся в режиме ожидания ввода-вывода, что может привести к нехватке потоков в основном пуле потоков .net.
В этом конкретном случае мы могли бы добавить семафор, чтобы ограничить создание до 100, поэтому, если 100 задач зависнут, 101-я задача не будет создана в первую очередь.
Есть ли способ специально создавать «задачи» в «пользовательских потоках/пуле потоков» вместо пула потоков .NET по умолчанию.
Это для фоновых задач, о которых я упоминал, поэтому в случае их задержки они не разрушат всю систему.
Можно переопределить и создать собственный TaskScheduler для передачи в Task.Factory.StartNew(), чтобы созданные задачи НЕ находились в пуле потоков .NET по умолчанию, а в каком-то другом пользовательском пуле.
Подробнее здесь: https://stackoverflow.com/questions/608 ... ation-to-c
Мобильная версия