Очень трудно найти подробное но простое описание рабочего и потоков ввода-вывода в.NET
Что ясно мне относительно этой темы (но может не быть технически точным):
Что не ясно:
Термин «рабочая нить» в .NET / CLR обычно относится к любому потоку, отличному от основной нити, которая выполняет некоторую «работу» от имени приложения, которое породило резьбу. «Работа» действительно может означать что-либо, в том числе ждать ввода-вывода. Threadpool сохраняет кэш рабочих потоков, потому что потоки дорогие для создания.
Термин «Three Threade i / O» в .NET / CLR относится к потокам резервов Threadpool, чтобы отправлять поперечные обратные вызовы от «перекрытых» вызовов Win32 (также известный как «Порт для доставки I / O»). CLR поддерживает свой собственный порт завершения ввода / вывода и может связывать любую ручку к ней (через API ThreadPool.bindhandle). Пример здесь: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx . Многие .NET APIS используют этот механизм внутренне, чтобы получать понравные обратные вызовы, хотя типичный разработчик .NET не будет использовать его напрямую.
На самом деле нет технической разницы между «рабочей нитью» и «Threade Thread» - они оба просто нормальные потоки. Но Threadpool CLR содержит отдельных пулов каждого простого, чтобы избежать ситуации, когда высокий спрос на рабочие потоки исчерпывает все потоки, доступные для отправки нативных обратных вызовов ввода-вывода, потенциально приводят к тупику. (Представьте себе приложение, используя все 250 рабочие потоки, где каждый ждет какой-либо ввода / вывода для завершения).
Разработчик должен заботиться при обработке обратного вызова ввода-вывода, чтобы убедиться, что поток ввода / вывода возвращается в ThreadPool - то есть код обратного копирования ввода / вывода должен выполнять минимальную работу, необходимую для Услуга обратного вызова, а затем вернуть управление нитью в Threadpool CLR. Если требуется больше работы, эта работа должна быть запланирована на рабочей нити. В противном случае прикладные риски «угоны» пул CLR зарезервированные потоки зарезервированных ввода / вывода для использования в качестве обычных рабочих потоков, приводящие к ситуации с тупиком, описанной выше.
Некоторые хорошие ссылки на дальнейшее чтение: Порты завершения Win32 ввода / вывода: http://msdn.microsoft.com/en-us/library/aaa365198 (vs.85) .aspx Управляемый Threadpool: http://msdn.microsoft.com/en-us/library/0ka9477y.aspx Пример bindhandle: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx
Кто-то с большим количеством навыков, чем я собирается прыгнуть здесь, чтобы помочь.
Рабочие нити имеют много состояния, они запланированы процессором и т. Д., И вы контролируете все, что они делают.
Порты завершения IO предоставляются операционной системой для очень конкретных задач, связанных с небольшим количеством общего состояния, и, таким образом, быстрее использовать. Хорошим примером в .NET - это Framework WCF. Каждый «вызов» на службу WCF фактически выполняется портом завершения IO, потому что они самые быстрые запуска, и ОС ухаживает за ними для вас.
Я начну с описания того, как асинхронный ввод / вывод используется программами в NT.
Вы можете быть знакомы с функцией API Win32 ReadFile (в качестве примера), которая представляет собой обертку вокруг нативной функции API NtreadFile . Эта функция позволяет делать две вещи с асинхронным ввода / выводом:
Однако есть третий способ быть уведомлен, когда операция ввода / вывода завершается. Вы можете создать порт завершения ввода / вывода объект и связывать файл ручек с ним. Всякий раз, когда операция завершена в файле, который связан с портом завершения ввода / вывода, результаты операции (например, состояние I / O) входит в очередь в порт завершения ввода-вывода. Затем вы можете настроить выделенный нить, чтобы удалить результаты из очереди и выполнить соответствующие задачи, такие как вызывающие функции обратного вызова. Это, по сути, какая «рабочая нить I / O».
нормальная «рабочая нить» очень похожа; Вместо того, чтобы удалить результаты ввода / вывода из очереди, он удаляет рабочие элементы из очереди. Вы можете покинуть рабочие элементы ( QueueUserWorkeTem ) и у рабочих потоков выполняются их. Это предотвращает необходимость вырезать нити каждый раз, когда вы хотите выполнить задачу асинхронно.
Просто поставить рабочую нить предназначена для выполнения короткого периода работы и будет удалять сам, когда он его завершил. Обратный вызов может использоваться для уведомления родительского процесса, который он завершен или сдать данные.
Тема ввода / вывода будет выполнять ту же операцию или последовательность операций, пока не остановится родительским процессом. Он так называется, потому что он, как правило, драйверы устройств работают непрерывно контролируют порт устройства. Тема ввода / вывода, как правило, создает события всякий раз, когда оно желает общаться с другими потоками.
Все процессы работают как потоки. Ваше приложение работает как поток. Любая нить может порождать потоки рабочих или потоков ввода / вывода (как вы их называете).
Всегда существует прекрасный баланс между производительностью и используемым числом или типом потоков. Слишком много обратных вызовов или событий, обрабатываемых процессом, будет серьезно ухудшить его производительность благодаря количеству перерывов к его основной цикле процесса, поскольку оно обрабатывает их.
Примеры рабочей нити будут добавлять данные в базу данных после взаимодействия пользователя или для выполнения длинных математических расчетов или записи данных в файл. Используя рабочую резьбу, вы освобождаете основное приложение, это наиболее полезно для GUI, так как он не замерзает, пока задача выполняется.