Простое описание streamов работника и ввода-вывода в .NET.
Очень сложно найти подробное, но простое описание рабочих и streamов ввода-вывода в .NET.
Что для меня ясно по этой теме (но, возможно, не технически точно):
- Рабочие streamи – это streamи, которые должны использовать процессор для их работы;
- Потоки ввода-вывода (также называемые streamами портов завершения) должны использовать драйверы устройств для их работы и, по существу, «ничего не делать», следить только за завершением операций без ЦП.
То, что не ясно:
- Разница между состояниями WAIT и BLOCKED
- Многопоточный рендеринг на OpenGL
- Реализация prologа
- Как JVM завершает streamи демона? или Как написать streamи демона, которые заканчиваются изящно
- Является ли HashMap streamобезопасным для разных ключей?
- Хотя метод ThreadPool.GetAvailableThreads возвращает количество доступных streamов обоих типов, кажется, что нет публичного API для планирования работы для streamов ввода-вывода. Создать рабочий stream в .NET можно только вручную?
- Кажется, что один stream ввода-вывода может контролировать несколько операций ввода-вывода. Это правда? Если да, то почему ThreadPool имеет так много доступных streamов ввода-вывода по умолчанию?
- В некоторых текстах я читал, что обратный вызов, инициированный после завершения операции ввода-вывода, выполняется streamом ввода-вывода. Это правда? Разве это не работа для рабочего streamа, учитывая, что этот обратный вызов является работой ЦП?
- Чтобы быть более конкретным – выполняйте асинхронные streamи ввода-вывода пользователя ASP.NET? Что такое преимущества производительности при переключении операций ввода-вывода для разделения streamа вместо увеличения максимального числа рабочих streamов? Это потому, что один stream ввода-вывода отслеживает несколько операций? Или Windows делает более эффективное переключение контекста при использовании streamов ввода-вывода?
- Несколько streamов пользовательского интерфейса - Winforms
- Контейнер Jboss Java EE и ExecutorService
- Двойная проверка блокировки в синглтоне
- StreamCorruptedException: неверный код типа: AC
- Android, как запуститьOnUiThread в другом classе?
- Как приостановить и возобновить stream в Java из другого streamа
- Дросселирование javafx gui обновлений
- Как вызвать метод пользовательского интерфейса из другого streamа
Термин «рабочий stream» в .net / CLR обычно относится только к любому streamу, отличному от основного streamа, который выполняет некоторую «работу» от имени приложения, породившего stream. «Работа» может действительно означать что угодно, включая ожидание завершения ввода-вывода. ThreadPool хранит кеш рабочих streamов, потому что streamи дороги для создания.
Термин «stream ввода-вывода» в .net / CLR относится к streamам, которые резервирует ThreadPool для отправки обратных вызовов NativeOverlapped из «перекрытых» вызовов win32 (также называемых «порт ввода-вывода портов»). CLR поддерживает собственный порт завершения ввода-вывода и может привязывать к нему любой дескриптор (через API ThreadPool.BindHandle). Пример здесь: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx . Многие API .net используют этот механизм для получения обратных вызовов NativeOverlapped, хотя типичный разработчик .net никогда не будет использовать его напрямую.
На самом деле нет технической разницы между «рабочим streamом» и «streamом ввода-вывода» – они оба являются просто нормальными streamами. Но CLR ThreadPool поддерживает отдельные пулы каждого, чтобы избежать ситуации, когда высокий спрос на рабочие streamи исчерпывает все streamи, доступные для отправки собственных обратных вызовов ввода-вывода, что потенциально приводит к взаимоблокировке. (Представьте приложение, использующее все 250 рабочих streamов, где каждый ожидает завершения ввода / вывода).
Разработчику необходимо проявлять осторожность при обработке обратного вызова ввода-вывода, чтобы гарантировать, что stream ввода-вывода будет возвращен в ThreadPool, то есть код обратного вызова ввода-вывода должен выполнить минимальную работу, необходимую для обслуживания обратного вызова а затем вернуть управление streamом в пул streamов CLR. Если требуется больше работы, эта работа должна быть запланирована на рабочем streamе. В противном случае приложение рискует «захватить» пул зарезервированных streamов ввода-вывода CLR для использования в качестве обычных рабочих streamов, что приведет к ситуации взаимоблокировки, описанной выше.
Некоторые хорошие ссылки для дальнейшего чтения: порты завершения ввода-вывода win32: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx управляемый stream: http://msdn.microsoft.com /en-us/library/0ka9477y.aspx пример BindHandle: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx
Начну с описания того, как asynchronous ввод-вывод используется программами в NT.
Вы можете быть знакомы с функцией Win32 API ReadFile (в качестве примера), которая представляет собой оболочку вокруг функции Native API NtReadFile . Эта функция позволяет выполнять две операции с асинхронным вводом / выводом:
- Вы можете создать объект события и передать его в NtReadFile . Это событие будет сообщено после завершения операции чтения.
- Вы можете передать функцию асинхронного вызова процедур (APC) в NtReadFile . По сути, это означает, что когда операция чтения завершается, функция будет поставлена в очередь на stream, который инициировал операцию, и будет выполняться, когда stream выполняет аварийное ожидание .
Тем не менее, существует третий способ получения уведомления о завершении операции ввода-вывода. Вы можете создать объект порта завершения ввода-вывода и связать с ним файлы. Всякий раз, когда выполняется операция над файлом, связанным с портом завершения ввода-вывода, результаты операции (например, состояние ввода-вывода) помещаются в очередь на порт завершения ввода-вывода. Затем вы можете настроить выделенный stream для удаления результатов из очереди и выполнения соответствующих задач, таких как вызов функций обратного вызова. По сути, это «рабочий stream ввода-вывода».
Обычный «рабочий stream» очень похож; вместо того, чтобы удалять результаты ввода-вывода из очереди, он удаляет рабочие элементы из очереди. Вы можете поставить в очередь рабочие элементы ( QueueUserWorkItem ) и выполнить рабочие streamи. Это не позволяет вам создавать stream каждый раз, когда вы хотите выполнить задачу асинхронно.
Проще говоря, рабочий stream предназначен для выполнения короткого периода работы и удалит себя, когда он его выполнит. Обратный вызов может использоваться для уведомления родительского процесса, который он завершил, или для передачи данных.
Поток ввода-вывода будет выполнять ту же операцию или последовательность операций непрерывно, пока не будет остановлен родительским процессом. Это так называется, потому что обычно драйверы устройств постоянно контролируют порт устройства. Поток ввода-вывода обычно создает события, когда он хочет общаться с другими streamами.
Все процессы выполняются как streamи. Ваше приложение работает как stream. Любой stream может создавать рабочие streamи или streamи ввода-вывода (как вы их называете).
Всегда есть хороший баланс между производительностью и количеством или типом используемых нитей. Слишком много обратных вызовов или событий, обрабатываемых процессом, сильно ухудшают его производительность из-за количества прерываний в его основном цикле процесса, когда он обрабатывает их.
Примерами рабочего streamа было бы добавлять данные в базу данных после взаимодействия с пользователем или выполнять длинный математический расчет или записывать данные в файл. Используя рабочий stream, вы освобождаете основное приложение, это наиболее полезно для графических интерфейсов, так как оно не зависает во время выполнения задачи.
Кто-то, у кого больше навыков, чем я, собирается прыгать сюда, чтобы помочь.
Рабочие streamи имеют много состояний, они запланированы процессором и т. Д., И вы контролируете все, что они делают.
Порты ввода-вывода ввода-вывода предоставляются операционной системой для выполнения очень конкретных задач с небольшим общим состоянием и, следовательно, быстрее используются. Хорошим примером в .Net является среда WCF. Каждый «вызов» службы WCF фактически выполняется портом завершения ввода-вывода, поскольку они быстрее всего запускаются, и ОС следит за ними за вас.