C # продолжение первого класса через взаимодействие C ++ или каким-либо другим способом? - PullRequest
32 голосов
/ 31 декабря 2011

У нас есть высокопроизводительная многозадачная программа, работающая почти на реальном времени на C #. Эта производительность была достигнута, в основном, за счет совместной реализации многозадачности с помощью собственного планировщика. Это часто называют микропотоками. В этой системе все задачи связываются с другими задачами через очереди.

Конкретная проблема, которую мы имеем, кажется, может быть решена только через продолжения первого класса, которые C # не поддерживает.

В частности, проблема возникает в 2 случаях, связанных с очередями. Всякий раз, когда какая-либо конкретная задача выполняет некоторую работу, прежде чем поместить элемент в очередь. Что, если очередь заполнена?

И наоборот, другая задача может выполнить некоторую работу, а затем потребуется удалить элемент из очереди. Что если эта очередь пуста?

Мы решили эту проблему в 90% случаев, связав очереди с задачами, чтобы избежать вызова задач, если какая-либо из их исходящих очередей заполнена или входящая очередь пуста.

Кроме того, некоторые задачи были преобразованы в конечные автоматы, чтобы они могли обрабатывать, если очередь заполнена / пуста, и продолжить без ожидания.

Реальная проблема возникает в нескольких крайних случаях, когда нецелесообразно принимать какое-либо из этих решений. Идея в этом сценарии состояла бы в том, чтобы сохранить состояние стека в точке и переключиться на другую задачу, чтобы он мог выполнить работу и впоследствии повторить задачу ожидания, когда сможет продолжить.

В прошлом мы пытались вернуть задачу ожидания обратно в расписание (рекурсивно), чтобы позволить другим задачам и позже повторить задачу ожидания. Однако это привело к слишком большому количеству «тупиковых» ситуаций.

Был где-то пример пользовательского хоста CLR, который заставлял потоки .NET фактически работать как "волокна", которые по существу позволяют переключать состояние стека между потоками. Но сейчас я не могу найти пример кода для этого. Кроме того, кажется, что для того, чтобы сделать это правильно, потребуются значительные сложности.

Есть ли у кого-нибудь еще творческие идеи, как эффективно переключаться между задачами и избегать вышеуказанных проблем?

Есть ли другие хосты CLR, которые предлагают это, коммерческое или иное? Есть ли какая-нибудь нативная библиотека дополнений, которая может предложить какую-то форму продолжений для C #?

Ответы [ 5 ]

2 голосов
/ 15 февраля 2012

Существует C # 5 CTP , который выполняет преобразование в стиле продолжения над методами, объявленными с новым ключевым словом async, и вызовы на основе продолжения при использовании ключевого слова await.

Это на самом деле не новая функция CLR, а скорее набор директив для компилятора для выполнения преобразования CPS над вашим кодом и несколько библиотечных подпрограмм для манипулирования и планирования продолжений.Записи активации для async методов помещаются в кучу, а не в стек, поэтому они не привязаны к конкретному потоку.

1 голос
/ 15 февраля 2012

На самом деле, мы определились с направлением.Мы используем шаблон Observer с передачей сообщений.Мы создали собственную библиотеку для обработки всех коммуникаций между «агентами», которые похожи на процесс Эрланга.Позже мы рассмотрим использование доменов приложений, чтобы еще лучше отделить агентов друг от друга.Идеи дизайна были заимствованы из языка программирования Erlang, который имеет чрезвычайно надежную многоядерную и распределенную обработку.

1 голос
/ 15 февраля 2012

Режим волокна был удален из версии 2 CLR из-за проблем в состоянии стресса, см .:

Насколько мне известно, поддержка оптоволокна еще не была добавлена, хотя после прочтения вышеупомянутых статей она может быть добавлена ​​ * (однако тот факт, что в течение 6-7 лет по этой теме ничего не упоминалось, делает я считаю, что это вряд ли).

Поддержка оптоволокна FYI должна была стать способом, позволяющим существующим приложениям, использующим оптоволокно (например, SQL Server), размещать CLR таким образом, который позволяет им максимизировать производительность, , а не в качестве метода, позволяющего Приложения .Net для создания множества потоков - в коротких волокнах не является волшебным решением вашей проблемы , однако, если у вас есть приложение, которое использует волокна и хочет разместить CLR, тогда API управляемого хостинга предоставляют средства, с помощью которых CLR «хорошо работает» с вашим приложением. Хорошим источником информации по этому вопросу была бы документация API управляемого хостинга , или чтобы посмотреть, как SQL Server размещает CLR, о чем есть несколько очень информативных статей.

Также быстро прочитайте Потоки, волокна, стеки и адресное пространство .

1 голос
/ 15 февраля 2012

Нет, не собираюсь на работу. C # (и даже IL) - слишком сложный язык, чтобы выполнять такие преобразования (CPS) в общем виде. Лучшее, что вы можете получить - это то, что предлагает C # 5. Тем не менее, вы, вероятно, не сможете разорвать / возобновить циклы / итерации более высокого порядка, чего вы действительно хотите от продолжений общего назначения.

0 голосов
/ 01 февраля 2012

Решением вашей проблемы является использование алгоритмов без блокировок, позволяющих в масштабе всей системы выполнить хотя бы одну задачу. Вам нужно использовать встроенный ассемблер, который зависит от процессора, чтобы убедиться, что вы атомарный CAS (сравнение и замена). В Википедии есть статья , а также шаблоны, описанные Дугласом Шмидтом книга под названием «Архитектура программного обеспечения на основе шаблонов, шаблоны для параллельных и сетевых объектов». Мне не сразу понятно, как вы будете это делать в рамках dotnet.

Другим способом решения вашей проблемы является использование шаблона публикации-подписчика или возможных пулов потоков.

Надеюсь, это было полезно?

...