Подробнее про ObxActions против Co_ObxActions.
Изначальный пример ObxActions в BlackBox вызывает за один цикл Services.Action (период около 50 миллисекунд) процедуру
Код:
   PROCEDURE Step (VAR cur, divisor: INTEGER; f: TextMappers.Formatter);
      VAR end, sqrtCur: INTEGER;
   BEGIN
      end := divisor + stepSize;
      sqrtCur := SHORT(ENTIER(Math.Sqrt(cur)));
      WHILE (divisor <= sqrtCur) & (divisor < end) & (cur MOD divisor # 0) DO divisor := divisor + 2 END;
      IF divisor > sqrtCur THEN   (* cur is a prime *)
         f.WriteInt(cur); f.WriteLn;
         divisor := 3; cur := cur + 2
      ELSIF divisor < end THEN   (* cur is not a prime, test next one *)
         divisor := 3; cur := cur + 2
      ELSE   (* time exhausted, continue test next time *)
      END
   END Step;
После одной итерации расчетов происходит выход из процедуры, чем завершается содержательная часть (a: PrimeAction) Do.
Пример с Co_ObxActions вызывается планировщиком Co_SchedTasks.
Код:
   PROCEDURE Do (t: Ct.Task) ;
      VAR a: PrimeAction; end, sqrtCur, n: INTEGER;
   BEGIN
      a := t(PrimeAction);
      FOR n := 0 TO a.attempts-1 DO
         a.current := 3; a.divisor := 3;
         REPEAT
            end := a.divisor + stepSize;
            sqrtCur := SHORT(ENTIER(Math.Sqrt(a.current)));
            WHILE (a.divisor <= sqrtCur) & (a.divisor < end) & (a.current MOD a.divisor # 0) DO 
               a.divisor := a.divisor + 2
            END;
            IF a.divisor > sqrtCur THEN   (* cur is a prime *)
               IF n = 0 THEN
                  a.f.WriteInt(a.current); a.f.WriteLn
               END;
               a.divisor := 3; a.current := a.current + 2
            ELSIF a.divisor < end THEN   (* cur is not a prime, test next one *)
               a.divisor := 3; a.current := a.current + 2
            END
         UNTIL a.current > a.to;
         Co.Yield
      END;
      Co.Stop
   END Do;
Здесь после каждой итерации вызывается Co.Yield, после чего управление передается планировщику. Планировщик смотрит, есть ли время до следующего цикла. По умолчанию (load_pct - может быть изменено) фоновым задачам отводится до 40% процессорного времени. Если есть время 40% от времени цикла - шаг планировщика повторяется и вновь вызывается задача Do.
Что выяснилось? За время 9 сек на моем компьютере пример ObxActions выполняется 1 раз (Upper Bound= 256), а Co_ObxActions выполняется 400000 раз (Upper Bound= 256, N Attempts= 400000). Значит, фоновая задача в  ObxActions использует имеющееся время неэффективно.
Иван Денисов писал(а):
А что тогда происходит во время срабатывания следующего цикла? Возврат в главную сопрограмму?
Каждый цикл Action вызывает планировщик Co_SchedTasks
Код:
   PROCEDURE (a: Action) Do ();
   BEGIN
      IF a.s.enabled THEN
         a.s.Step(a.s); Services.DoLater(a, a.s.p.interval)
      END
   END Do;
А Step планировщика передает управление сопрограммам и получает управление назад, когда те делают Co.Yield.
Info писал(а):
Правильно я понимаю, что это что-то вроде специального фонового Action'а, который добавляет опций управления очередью Экшенов сверх тех, что есть в ББ?
Один Action, на нем висит планировщик, он управляет очередью сопрограмм.