Это немного сложно объяснить, но я в основном ищу идеи сделать «интересные вещи» с перечислениями, а теперь и задачами. Все начнется с бесконечного перечисления, чтобы бросить 6-гранный кубик:
public static IEnumerable<int> Roll()
{
while (true) { yield return new Random().Next(1, 7); }
}
Это не слишком увлекательно и служит примером для работы. То, что я хочу, идет глубже ... И включает в себя еще несколько генетических, статических методов. Например:
public static IEnumerable<T> Clock<T>(this IEnumerable<T> source, long totalMs)
{
var sw = new Stopwatch();
foreach (var item in source)
{
if (!sw.IsRunning) { sw.Restart(); }
if (sw.ElapsedMilliseconds < totalMs) { yield return item; }
else { yield break; }
}
}
Этот метод будет продолжать циклически проходить по перечислению, пока не истечет время. Протестировал и все отлично работает. Теперь я могу использовать это: Dice.Roll().Clock(1000)
и мой код будет бросать кубики за одну секунду. И я теперь сделал этот метод:
public static IEnumerable<int> Roll3(this IEnumerable<int> rolls)
{
int count = 0, total = 0;
foreach (var die in rolls)
{
count += 1;
total += die;
if (count == 3)
{
yield return total;
count = 0;
total = 0;
}
}
}
Это может быть написано немного лучше, но это все еще пример. (Используя Take (3) в цикле ...) Но он использует предыдущее бесконечное перечисление следующим образом: Dice.Roll().Clock(1000).Roll3()
Но теперь сложная часть: у меня также есть метод для вычисления общей стоимости всех бросков ипосчитать количество рулонов. Эти методы:
public static IEnumerable<int> Sum(this IEnumerable<int> rolls)
{
int total = 0;
foreach (var die in rolls)
{
total += die;
yield return total;
}
}
public static IEnumerable<int> Count(this IEnumerable<int> rolls)
{
int count = 0;
foreach (var die in rolls)
{
count += 1;
yield return count;
}
}
А теперь настоящая проблема ... Мой код может следовать только одному перечислению, но я делю его на два перечисления. И каждый из них затем разделяется на сумму, сумму и само перечисление. Вышеприведенные методы не могут быть изменены , но я бы хотел увидеть что-то вроде:
Dice.Roll().Clock(1000).Sum().Total().Roll3().Sum().Total();
Но это не получается, очевидно. Именно здесь должны будут использоваться задачи, и я начну выполнять магию многозадачности.
Мне нужен такой метод:
public static IEnumerable<T> SplitPipeLine<T>(this IEnumerable<T> source, **something**)
{
foreach (var item in source)
{
yield return item;
**Something with task**
}
}
Или, может быть, какое-то другое решение,Я могу себе представить, что эта задача является своего рода ConcurrentQueue, который будет содержать входящие значения для обработки, которые будут выполняться параллельно с основным перечислением. Так как оба связаны с исходным перечислением, на самом деле не имеет значения, работает ли один быстрее другого. Но я ищу умный способ отделить методы Sum () и Total () от исходного перечисления и от перечисления Roll3 (). Итак, одно перечисление, которое разбито на шесть различных конвейеров ...
Каждый конвейер должен работать внутри своего собственного потока, предпочтительно ... И да, это сложно и, вероятно, может быть решено другими способами. Мне просто любопытно, есть ли какой-нибудь способ решить это таким образом.
Идея состоит в том, что каждый конвейер будет в основном обеспечивать живых результатов на одном перечислении, пока оно перечисляет. Итак, как мне разделить перечисление на несколько перечислений из одного и того же списка? Что-то вроде этого, возможно?
Dice.Roll().Clock(1000).Split(Sum).Split(Total).Split(Roll3, Sum, Total);
Это будет сложно для конвейера Roll3 (), так какоригинальное перечисление Roll () будет в цикле ForEach для основного отображения значений. Остальные - статистика ...