У нас очень высокопроизводительное многозадачное приложение C #, работающее почти в реальном времени. Эта производительность была достигнута в основном за счет реализации совместной многозадачности внутри компании с помощью собственного планировщика. Это часто называют микропотоками. В этой системе все задачи общаются с другими задачами через очереди.
Конкретная проблема, которая у нас есть, кажется, может быть решена только с помощью первоклассных продолжений, которые C # не поддерживает.
В частности, проблема возникает в двух случаях, связанных с очередями. Всякий раз, когда какая-либо конкретная задача выполняет некоторую работу перед помещением элемента в очередь. Что делать, если очередь заполнена?
И наоборот, другая задача может выполнить некоторую работу, и затем потребуется удалить элемент из очереди. Что, если эта очередь пуста?
Мы решили эту проблему в 90% случаев, связав очереди с задачами, чтобы избежать вызова задач, если какая-либо из их исходящих очередей заполнена или входящая очередь пуста.
Кроме того, некоторые задачи были преобразованы в конечные автоматы, чтобы они могли обрабатывать, если очередь заполнена / пуста, и продолжать работу без ожидания.
Настоящая проблема возникает в нескольких крайних случаях, когда нецелесообразно применять любое из этих решений.Идея в этом сценарии состоит в том, чтобы сохранить состояние стека в этой точке и переключиться на другую задачу, чтобы она могла выполнять работу и впоследствии повторять выполнение ожидающей задачи, когда она сможет продолжить.
Раньше мы пытались включить вызов ожидающей задачи обратно в расписание (рекурсивно), чтобы позволить другим задачам, а затем повторить попытку ожидающей задачи. Однако это привело к слишком большому количеству «тупиковых» ситуаций.
Где-то был пример настраиваемого хоста CLR, чтобы потоки .NET фактически работали как «волокна», что по существу позволяет переключать состояние стека между потоками. Но сейчас я не могу найти для этого образец кода. К тому же, кажется, потребуется немало сложностей, чтобы сделать это правильно.
Есть ли у кого-нибудь другие творческие идеи, как эффективно переключаться между задачами и избегать вышеуказанных проблем?
Есть ли другие хосты CLR, которые предлагают это, коммерческое или иное? Есть ли какая-нибудь дополнительная собственная библиотека, которая может предложить некоторую форму продолжения для C #?