Re[16]: Асинхронная операция в рамках одного потока?
От: TK Лес кывт.рф
Дата: 04.10.05 17:21
Оценка:
Hello, "Tom"
>
> ReadFileEx это синхронный вызов, и он сразу возвращает результат. Не
> путать асинхронынй вызов с асинхронным чтением (см выделенное). Вот если
> запустить поток в котором вызвать ReadFileEx это будет асинхронный вызов
> ReadFileEx, опять же не путать с асинхронным чтением.

Молодец, уже лучше Только как-то не аккуратненько... Запуск потока это
запуск потока, вызов ReadFileEx это вызов ReadFileEx (вызываешь ты ее все
равно синхронно). Где асинхронность вызова ReadFileEx-то? На да ладно...

Давай лучше разберем FileStream.BeginRead — где тут потоки и кто их создает?
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[16]: Асинхронная операция в рамках одного потока?
От: GlebZ Россия  
Дата: 04.10.05 17:23
Оценка:
Здравствуйте, Аноним, Вы писали:

Повторяться не буду. Ответ на твой вопрос уже прозвучал во флейме, и он был однозначный.

С уважением, Gleb.
Re[17]: Асинхронная операция в рамках одного потока?
От: Tom Россия http://www.RSDN.ru
Дата: 04.10.05 17:47
Оценка:
TK>Давай лучше разберем FileStream.BeginRead — где тут потоки и кто их создает?
Ты эта, перечитай моё сообщение на которое ты ответил (6 твоих постов назад)

А ты говоришь понятия понятия
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Народная мудрось
всем все никому ничего(с).
Re: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:00
Оценка: 6 (1) +1
Здравствуйте, <Аноним>, Вы писали:

А>По мотивам

А>http://blogs.gotdotnet.ru/personal/mihailik/PermaLink.aspx?guid=8a4d8bd1-a926-4d19-83c7-f126f9cb14de
А>Цитата — "Многопоточность — это много потоков. А асинхронность — это как правило один поток, который грамотно распоряжается рабочим временем."
А>и частично
А>http://rsdn.ru/Forum/?mid=1208906
Автор: mihailik
Дата: 06.06.05


А>Существует ли пример, когда асинхронная операция выполняется в вызывающем потоке, причем оправданно? (Оправданно — в смысле что тоже самое не может работать также эффективно синхронно)

А>Собственно смущает статус MVP человека, написавшего это.

Асинхронность ассинхронности резнь. Полноценная ассинхронность конечно без многопоточности недоступна. Однако в виндовс есть поддержка так называемоей кооперативной многопоточности. Еще до выхода NT и 95-ых виндовс предоставляла эту возможность. Суть ее очень проста. Интерактивное приложение не все время потребляет процессорное время. Более того, 99% времени оно попросту спит. "Спит" — означает что приложение передает управление ОС и ждет от нее отклика. Для этого приложение вызвает АПИ-шный метод GetMessage(). Если в очреди потока помещается сообщение ОС передает его приложению возвращая управление из GetMessage().

Так вот на этом механизме можно реализовать ассинхронность.
Вариатны есть следующие:
1. Создать таймер. При каждом его срабатывании Виндовс будет помещать в очередь потока сообщение WM_TIMER обрабатывая которое приложение может делать некоторые действия в основном GUI-потоке. Если это действие не занимает много времени (ну, например, обровление отображаемой информации), то создается эллюзия многопоточной работы. Обрабатывается WM_TIMER только когда в очереди нет других собщений и в самую последнюю очередь (грубо говоря вытесняется).
2. Можно послать себе же ассинхронное сообщение. Для этого нужно использовать функцию PostMessage. Этот метод помещает сообщение в очередь потока, но при этом сразу же возвращает уравление. К тому же сообщения посланные этим методом имеют более низкий приоритет и разбираются после того как будут разобраны все синхронные сообщения.

Собственно все эти способы точно так же доступны в WinForms-приложениях. Так что организовать ассинхронность, хотя и не полноценную, таки можно и имея только один поток. Так у класса Control есть методы BeginInvoke которые реализован какраз через PostMessage. Ну, и само собой есть контрол основанный на виндовом таймере.


Во втором фрэймворке, кстати, еще появились "легкие потоки", т.е. файберы. Они тоже позволяют эмулировать ассинхронность в рамках одного потока. Правда это я еще не копал.

ЗЫ

Что же касается BeginRead, то почти уверен, что там используются теневые потоки. Ведь работу по чтению должен кто-то делать. А если основной поток приложения занят, то это должен быть другой поток. Так что вопрос там только в том преложена ли реализация ассинхронного чтения на ОС, или же реализована вручную. Хотя все это уже особенности реализации. Для программиста все прозрачно.

Собственно, что трепаться то? Проще проверить.
Делаем по бырому тестик:
using System;
using System.Threading;
using System.Text;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        using (FileStream fs = File.OpenRead(@"C:\boot.ini"))
        {
            Console.WriteLine("Main:");
            Console.WriteLine("    IsThreadPoolThread: "
                + Thread.CurrentThread.IsThreadPoolThread);
            Console.WriteLine("    Current Thread ID: "
            + AppDomain.GetCurrentThreadId());

            byte[] array = new byte[fs.Length];
            IAsyncResult ar1 = fs.BeginRead(array, 0, array.Length,
                delegate(IAsyncResult ar2)
                {
                    Console.WriteLine("Callback:");
                    Console.WriteLine("    IsThreadPoolThread: "
                        + Thread.CurrentThread.IsThreadPoolThread);
                    Console.WriteLine("    Current Thread ID: "
                    + AppDomain.GetCurrentThreadId());
                }, null);

            while (!ar1.IsCompleted)
                Thread.Sleep(100);

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Считанные данные:");
            Console.WriteLine(Encoding.Default.GetString(array));
        } 
    }
}

и запускаем... у меня он вывел:
Main:
        IsThreadPoolThread: False
        Current Thread ID: 2584
Callback:
        IsThreadPoolThread: True
        Current Thread ID: 2920


Считанные данные:
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(3)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(3)\WINDOWS="Microsoft Windows XP Professional" /fastdetect /NoExecu
te=OptIn
multi(0)disk(0)rdisk(0)partition(4)\WINDOWS="Windows XP Professional x64 Edition" /fastdetect
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Windows Server 2003, Enterprise" /fastdetect

Из чего можно сделать вывод:
1. Обратный вызов делается в другом потоке.
2. Это поток из дотнетного пула, так что скорее всего ассинхронность реализована в данном случае в недрах дотнета.

Так что или Михалик говорит о том что все это не проблемы программиста, так как последний может просто проверять резултат чтения в рамках одного потока. Или он все же ошибается.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:29
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, Аноним, Вы писали:


А>>Нарушается мое условие которое я поставил в первом сообщении топика "(Оправданно — в смысле что тоже самое не может работать также эффективно синхронно)".

GZ>Тебе уже указали. В принципе, любая работа ввода-вывода с периферийного устройства. Копирование данных память-устройство происходит не через процессор, а через каналы DMA и не требуют потока. Заниматься такой фигней как ожидание, в это время смысла нет.

DMA это проблемы ОС. А в виндовс ты работашь с некоторым АПИ. И тут или Виндузный OVERLAPPED, или ручная ассинхронность на потоках. Так как FileStream не требует задавать ассинхронность при открытии файла (а OVERLAPPED требует), то скорее всего фрэймворк эмулирует ассинхронность самостоятельно. Ну, и естественно он это делает на потоках из пула, что подтверждается простеньким тестом
Автор: VladD2
Дата: 05.10.05
.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:29
Оценка:
Здравствуйте, mihailik, Вы писали:

M>Хотя тут обсуждался больше BeginRead для FileStream, наиболее наглядная выгода от асинхронности (по сравнению с многопоточностью) появляется в сетевых приложениях.


Ты бы пояснил, что ты вкладывашь в поняте "ассинхронность", а что в "многопоточность". А то из твоих слов я лично могу сделать вывод, что под многопоточностью ты не понимашь ассинхронность. Ведь ты как бы противопоставляшь эти вещи.

Что касается "BeginRead для FileStream", погляди, плиз вот это
Автор: VladD2
Дата: 05.10.05
(тест в конце). Ну, и соотвествнно объясни как ты понимашь в данном случае многопоточность и ассинхронность.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:29
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>А уведомление вызывающего потока о завершении работы ввода-вывода создаст и отдаст тоже DMA канал?


В FileStream поток не уведомляется. Там уведомление посылается в другой поток
Автор: VladD2
Дата: 05.10.05
.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:29
Оценка: -1
Здравствуйте, TK, Вы писали:

TK>От себя могу сказать, что вызов делегата через BeginInvoke тоже ничего не

TK>гарантирует.

Ну, он точно гарантирует запуск в другом потоке. Другое дело, что начиная со второго фрэймворка это может быть "легкий поток", т.е. по сути файбер. А файберы явно не катят в качестве оповещения о завершении операции.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 03:34
Оценка:
Здравствуйте, Andrbig, Вы писали:

A>кто-нить может привести код с асинхронной работой FileStream.BeginRead?


Re: Асинхронная операция в рамках одного потока?
Автор: VladD2
Дата: 05.10.05
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 04:44
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Асинхронный вызов означает что вызывающий поток не ожидает результат вызова и тогда вызов асинхронен относительно вызывающего потока.


Ага. Вот только ассинхронное опвевещение (колбэк) таки без другого потока не какти.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 04:44
Оценка:
Здравствуйте, TK, Вы писали:

TK>Вот только не надо все в одну кучу мешать. Пример с асинхронными операциями

TK>подразумевает 2 принципиально различных действия (в одном задействован
TK>процессор а в другом жесткий диск).
TK>Переводя на пловцов это будет "пока ты тут плавал, твою машину со стоянки
TK>...сперли".

DMA и физические девайсы это конечно здорово. Но читается то файл, а не физические кластеры на диске. Там еще нужно сигналы на шину подать и т.п. Когда используется DMA для оповещении о завершении операции используются IRQ, а в них не то что вызвать колбэк нельзя. В них вообще нужно по проворнее двигаться. Файловые же системы это отдельный и не маленький код, так что потоки ОС там по любому присутствуют. Должен же кто-то дать команды на чтение кластеров, преобразовать это все в буфер и установить событие?
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 04:44
Оценка:
Здравствуйте, VladD2, Вы писали:

GZ>>Тебе уже указали. В принципе, любая работа ввода-вывода с периферийного устройства. Копирование данных память-устройство происходит не через процессор, а через каналы DMA и не требуют потока. Заниматься такой фигней как ожидание, в это время смысла нет.


VD>DMA это проблемы ОС. А в виндовс ты работашь с некоторым АПИ. И тут или Виндузный OVERLAPPED, или ручная ассинхронность на потоках. Так как FileStream не требует задавать ассинхронность при открытии файла (а OVERLAPPED требует), то скорее всего фрэймворк эмулирует ассинхронность самостоятельно. Ну, и естественно он это делает на потоках из пула, что подтверждается простеньким тестом
Автор: VladD2
Дата: 05.10.05
.


Глянул, Рефлектором. Там все же OVERLAPPED. Однако не ясно как это прокатывает. Ведь как минимум в 95-ых с этим большие проблемы. Да и пользуются для чтения они все же ReadFile, а не ReadFileEx.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 05:14
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Он показывает, что асинхронный делегат в BeginInvoke будет вызываться в том же потоке, и будет вызван не во время работы вызывающей функции а только после.


Не, ну, это ты уже совсем пургу несешь. Причем тут "асинхронный делегат" и "очереди окна"? Ненадо путать Control.BeginInvoke и Delegate.BeginInvoke. Это разные вещи. Один осуществляет передачу управления в GUI-поток по средстам посылки сообщения через PostMessage, а второй просто вызвает метод в одном из потоков пула.

GZ>MSDN — не указ, код мы не читаем. Рычаги давления кончились, пойду домой и забуду про этот флейм. Благо смысла в нем, не на грош.



Вы ребятки разговариваете о разных вещах, да еще и перепрыгивая на разные уровни абстракции.

Короче в голове каша. Давайте как приведем все в порядк.

Итак, чтение из файла в Виндовс действительно может делаться ассинхронно если исползуется Overlapped I/O. При этом внутри Виндовс параллельность чтения осуществляется довольно сложными механизмами где без рабочих потоков вряд ли можно обойнись. Но думаю Том говорит не об этом. Том говорит о том, что чтобы уведомить приложение о завершении операции как не крути нужно сделать это в другом потоке. Ведь этот поток необязан быть GUI-потоком, и уж темболее не обязан постоянно выбирать очередь приложения чтобы обрабоаться какие-то там сообщения посланные PostMessage-ом. Так что для оповещения поток нужен по любому.

Другое дело, что на колбэк можно забить и тогда по крайней мере для прикладного программиста никаких других потоков видно не будет.

Так что все одновременно и правы, и не правы. Смотря как посмотреть.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 05:23
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>2. Это поток из дотнетного пула, так что скорее всего ассинхронность реализована в данном случае в недрах дотнета.


Поглядел Рефлектором... Чтение делается через Overlapped I/O, но оповещение идет из потока пула. Там вообще все довольно хитро устроено. Без пол литры не разберашся. Оповещение приходит из _IOCompletionCallback.PerformIOCompletionCallback().
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Асинхронная операция в рамках одного потока?
От: mihailik Украина  
Дата: 05.10.05 05:46
Оценка: 35 (3) +1
VD>Итак, чтение из файла в Виндовс действительно может делаться ассинхронно если исползуется Overlapped I/O. При этом внутри Виндовс параллельность чтения осуществляется довольно сложными механизмами где без рабочих потоков вряд ли можно обойнись.

Некоторые операции выполняются без потоков. Для драйверов есть традиция выполняться определённый код в контексте первого попавшегося потока.

Когда приходит прерывание, обработчик вызывается прямо в контексте того потока, который сейчас выполняется на процессоре.

Впрочем, другая часть кода драйверов ввода-вывода выполняется в так называемых "системных" потоках, то есть в отдельном пуле потоков в процессе System (его можно увидеть в Task Manager рядом с System Idle).


Мало того, внутри архитектуры NT (Windows NT, 2000, XP, 2003) операции ввода-вывода всегда выполняются асинхронно. Чтобы мы там не указывали в FileStream-конструкторе или в системном вызове CreateFile. Для чтения из файла создаётся определённым образом сформатированый IRP-запрос драйверу, и этот запрос "путешествует" и выполняется разными частями ОС асинхронно. Фактически, в процессе одной операции чтения запрос может обрабатываться в одном, другом, третьем системном потоке — как получится.

Для более верхнего уровня — Win32 API или FileStream — вся эта асинхронность скрыта, и для программиста есть как правило два способа вызова: синхронный и асинхронный. Но всё равно в обоих случаях реальное выполнение будет происходить асинхронно с использованием как специально выделеных системных потоков, так и иногда "первых попавшихся" пользовательских. Просто синхронная работа как бы "эмулируется" на определённом низком уровне API.


Для того, чтобы жизнь мёдом не казалась, можно упомянуть ещё такую системную концепцию из области драйверов файловых систем, как Fast IO. Она тоже относится к оптимизации синхронности-асинхронности, как раз для случая быстрых "маленьких" операций выполняя их "более синхронно".

* * *

Общая мысль такова. Если вы создаёте свой собственный отдельный поток для операций ввода-вывода, вы неэкономно расходуете ресурсы. Так как всё равно за кулисами при выполнении операций I/O будут задействованы разные системные потоки, создание ещё и своего отдельного неуместно. Лучше "положиться" на существующий механизм, то есть задейстовать именно асинхронные вызовы.

А для желающих получить краткий и чёткий ответ, используется ли отдельный поток для BeginRead, надеюсь ситуация стала немного сложнее. Потому что чёткий ответ здесь будет совсем не кратким.
Re[19]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 06:08
Оценка:
Здравствуйте, mihailik, Вы писали:

Хороший ответ!

M>Общая мысль такова. Если вы создаёте свой собственный отдельный поток для операций ввода-вывода, вы неэкономно расходуете ресурсы. Так как всё равно за кулисами при выполнении операций I/O будут задействованы разные системные потоки, создание ещё и своего отдельного неуместно. Лучше "положиться" на существующий механизм, то есть задейстовать именно асинхронные вызовы.


А здесь я бы поспорил. Тут все зависит от задачи. Если чтение файла само по себе производится в контексте некоторой ассинхронной операции, то смысла в ассинхронном чтении все нет. Поток то все равно заводить. Ну, и опять же потом можно взять из пула. Так что тут наверно лучше думать как уобнее, а не как экономнее.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Асинхронная операция в рамках одного потока?
От: GlebZ Россия  
Дата: 05.10.05 07:28
Оценка:
Здравствуйте, VladD2, Вы писали:

А>>>Нарушается мое условие которое я поставил в первом сообщении топика "(Оправданно — в смысле что тоже самое не может работать также эффективно синхронно)".

GZ>>Тебе уже указали. В принципе, любая работа ввода-вывода с периферийного устройства. Копирование данных память-устройство происходит не через процессор, а через каналы DMA и не требуют потока. Заниматься такой фигней как ожидание, в это время смысла нет.

VD>DMA это проблемы ОС. А в виндовс ты работашь с некоторым АПИ. И тут или Виндузный OVERLAPPED, или ручная ассинхронность на потоках. Так как FileStream не требует задавать ассинхронность при открытии файла (а OVERLAPPED требует), то скорее всего фрэймворк эмулирует ассинхронность самостоятельно. Ну, и естественно он это делает на потоках из пула, что подтверждается простеньким тестом
Автор: VladD2
Дата: 05.10.05
.

В данном случае — это был конкретный ответ на конкретный вопрос. В более полном виде написал mihailik. Просто тут более низкий уровень(и мой прошлый опыт).

С уважением, Gleb.
Re[6]: Асинхронная операция в рамках одного потока?
От: GlebZ Россия  
Дата: 05.10.05 07:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, GlebZ, Вы писали:


GZ>>Асинхронный вызов означает что вызывающий поток не ожидает результат вызова и тогда вызов асинхронен относительно вызывающего потока.


VD>Ага. Вот только ассинхронное опвевещение (колбэк) таки без другого потока не какти.

Асинхронный вызов не обязательно должен приводить к асинхронному оповещению.
Что касается асинхронного оповещения, то это можно эмулировать и через какую-либо систему очередей в том же потоке. Ну, например, WM_TIMER. Просто через поток удобнее, хотя иногда обходится дороже.

С уважением, Gleb.
Re[12]: Асинхронная операция в рамках одного потока?
От: GlebZ Россия  
Дата: 05.10.05 08:00
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Глянул, Рефлектором. Там все же OVERLAPPED. Однако не ясно как это прокатывает. Ведь как минимум в 95-ых с этим большие проблемы. Да и пользуются для чтения они все же ReadFile, а не ReadFileEx.

Дело в том, что ReadFile нормально работает со структурой OVERLAPPED и для синхронного чтения. Там если отсутсвует флаг какой-то при открытии, но OVERLAPPED то идет синхронный вызов но с работой по структуре оверлаp. Сам как-то делал такую штуку для эмуляции асинхронности в Win95. Весьма удобно.

С уважением, Gleb.
Re[7]: Асинхронная операция в рамках одного потока?
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.10.05 09:20
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Что касается асинхронного оповещения, то это можно эмулировать и через какую-либо систему очередей в том же потоке. Ну, например, WM_TIMER. Просто через поток удобнее, хотя иногда обходится дороже.


Заблуждаешся. WM_TIMER не работает если нет выборки сообщений, т.е. сервисы, консольные приложения и т.п. Ну, и WM_TIMER обрабатывается только при прокачке сообщений, а оповещения должны и без них работать. Так что кроме отдельного потока тут ничего другого быть не может.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.