Нам еще нужен Richter AsyncEnumerator?

Недавно я наткнулся на класс класса AsyncEnumerator, представляющий библиотеку потоковой обработки Джеффри Рихтера, которая, кажется, решает несколько проблем, с которыми я обычно сталкиваюсь при программировании асинхронного материала.

Идея для этого класса существует довольно давно, и мне интересно, есть ли в настоящее время версии .NET/С# встроенная поддержка этого механизма или если еще нужно полагаться на третью партийная библиотека? Или, может быть, в более новых версиях .NET есть альтернативный подход, который упрощает асинхронное программирование так же, как и Richter AsyncEnumerator?

Или, другими словами: есть ли причина, чтобы сегодня не использовать Richter AsyncEnumerator?

Edit:

Некоторые ссылки с информацией об AsyncEnumerator:

Ответ 1

Да, вы по-прежнему будете пользоваться моим AsyncEnumerator. Новые потоки, введенные в .NET 4 (Tasks, Parallel, PLINQ и т.д.), Касаются concurrency. То есть все они занимаются вычислительной нагрузкой, делят ее и размножают на несколько потоков, так что рабочая нагрузка может завершиться за меньшее время, чем потребуется 1 поток для выполнения всей рабочей нагрузки. Вы можете использовать эти конструкции для одновременного выполнения нескольких операций синхронного ввода-вывода. Тем не менее, операции синхронного ввода-вывода приводят к блокировке всех потоков, которые затем заставляют threadpool создавать больше потоков. Таким образом, ваше использование ресурсов приложений растет, а использование вашего процессора остается очень низким. Это очень неэффективно для реализации вашего приложения и предотвращает масштабирование вашего приложения.

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

В следующей версии .NET новые функции языка асинхронного/ждущего языка (которые я работал с Microsoft) позволяют выполнять асинхронные операции ввода-вывода, и на самом деле новые функции моделируются очень похоже на мой AsyncEnumerator. Настолько, что вы можете использовать порт, который использует мой AsyncEnumerator для новой модели с очень небольшим количеством изменений исходного кода.

Как заметил кто-то другой, мой AsyncEnumerator по-прежнему предлагает другие функции и работает с .NET 2.0 и более поздними версиями. Таким образом, многие люди все равно найдут это весьма полезным в течение длительного времени.

Ответ 2

Очевидной параллелью здесь является PLINQ, но сам Рихтер отклоняет это:

Джеффри Рихтер 04 декабря 2008 года в 2:27 PMquotereply Они очень другой. Параллельно. В частности, речь идет о выполнении операции, связанные с вычислением, параллельное масштабирование по всем процессорам в машине. Мой AsyncEnumerator в основном связан с выдачей одного или нескольких одновременные операции с привязкой к вводу/выводу, без каких-либо блоков потоков для их завершать.

Однако С# async CTP может быть полезен здесь, делая продолжения потоков гораздо более разумными, т.е.

var bytesRead = await stream.ReadAsync(...);
Console.WriteLine(bytesRead); // woah! we're on a different thread now!

Здесь компилятор С# переписывает все вокруг await instксов, так что он становится обратным вызовом/продолжением существующей операции async (которая должна возвращать "ожидаемое" значение). Как только это будет в производстве, я надеюсь, что это станет намного более естественным способом написания кода с внутренними задержками из-за асинхронности.

Ответ 4

Из этого вопроса Асинхронный итератор Задача < IEnumerable <T → > :

Похоже на то, что вы действительно ищете, это что-то вроде IObservable <T> , что похоже на push-based асинхронный IEnumerable <T> . См. Реактивные расширения, а также Rx от Microsoft Open Technologies (код, лицензированный под Apache-2.0) (без привязки) для огромного множества методов, которые работают с IObservable <T> чтобы он работал как LINQ-to-Objects и многое другое.

Проблема с IEnumerable <T> заключается в том, что нет ничего, что действительно делает само перечисление асинхронным. Если вы не хотите добавлять зависимость от Rx (что действительно делает IObservable <T> shine), эта альтернатива может работать для вас:

public async Task<IEnumerable<char>> TestAsync(string testString)
{
    return GetChars(testString);
}

private static IEnumerable<char> GetChars(string testString)
{
    foreach (char c in testString.ToCharArray())
    {
        // do other work
        yield return c;
    }
}

хотя я хотел бы указать, что, не зная, что на самом деле выполняется асинхронно, может быть намного лучший способ достичь ваших целей. Ни один из написанных вами кодов не будет делать асинхронно, и я действительно не знаю, является ли что-либо в // do other work асинхронным (в этом случае это не решение вашей основной проблемы, хотя оно сделает ваш код компиляцией).