C # 5 / Task Library будет переписывать мои вызовы методов? - PullRequest
1 голос
/ 05 ноября 2010

Мне нужно разобраться с некоторыми асинхронными вещами.

Допустим, я хочу загрузить большой файл.Насколько я понимаю, есть разница в том, чтобы просто вызывать File.Read() и ставить его в очередь в пул потоков или использовать Begin - / EndRead API.

Насколько я знаю, если вы используете API BeginFoo / EndFoo, вы даже не блокируете какой-либо поток, а вместо этого аппаратные средства просто перезвонят вам, когда закончат свою работу.Напротив, раскручивание потока из ThreadPool означает, что вы по крайней мере блокируете этот конкретный поток для работы, которая на самом деле не связана с процессором ...

Пока все хорошо.

Интересно, что на самом деле делает библиотека задач, если я использую File.Read?Достаточно ли умен, чтобы изменить мой код для использования BeginFoo / EndFoo API?Или это просто раскрутит нить от ThreadPool?

Если это действительно меняет мой код, мне интересно, как далеко он отыщет мой код для перезаписи вызовов методов?

Имеет ли это какой-то смысл?

Помогите мне, пожалуйста!

Ответы [ 2 ]

3 голосов
/ 13 декабря 2010

Вы говорите, что удивляетесь, если «библиотека задач» изменит ваш код.Есть две отдельные части - Task Parallel Library (которая доступна сегодня с поставкой в ​​.NET 4.0) и новая асинхронная программа C #, которая будет поставляться с C # v5.

Асинхронная программа C # сама разбитана две вещи: функции компилятора и сопровождающая библиотека.Не совсем понятно, что будет в библиотеке, когда она наконец появится, - сегодня они добавили туда некоторые методы расширения, которые добавляют методы к Task и несколько других существующих типов библиотек классов (например, WebClient) для созданияони работают гладко с новыми функциями компилятора.Некоторые вещи в этой специфической для C # библиотеке, которая поставляется сегодня, вполне могут стать частью библиотеки классов .NET Framework, когда наконец выйдет C # 5.Тем не менее, в настоящее время представляется вероятным, что будут некоторые вещи, которые могут не принадлежать к основной библиотеке классов фреймворка, но некоторые из них могут переместиться в вспомогательную DLL, например ту, которую вы должны использовать, если вы хотите dynamic сегодня.

Итак, с этим фоном должно быть ясно, что библиотека задач никогда не будет переписывать ваш код, потому что она уже там сегодня, и это просто библиотека.

Компилятор переписает ваш код,но он делает это в основном так же, как сегодня делают итераторы: он возьмет то, что выглядит как один последовательный метод, и разделит его на несколько методов, добавив некоторое отслеживание состояний, чтобы позволить методу забрать с того места, где он остановился.

Компилятор не заменит Read на BeginRead.На самом деле C # 5 даже ничего не знает об модели асинхронного программирования.(APM - это официальное название для шаблона BeginFoo / EndFoo.) C # 5 требует очень специфического шаблона при использовании ключевого слова await, которое не совсем похоже ни на один из асинхронных шаблонов, существующих сегодня,именно поэтому асинхронный предварительный просмотр поставляется с библиотекой, которая предоставляет методы расширения для Task - он добавляет методы, ожидаемые в C # 5.

(Так что, для ясности, в C # 5 нетспециальная обработка для Task, когда дело доходит до , потребляющего асинхронных операций. Напротив, асинхронный предварительный просмотр должен был использовать некоторые дополнительные методы для Task только для того, чтобы он работал. Тем не менее, C # 5имеет специальную обработку для Task на стороне поставщика - он может генерировать код, который создает новое Task в качестве возвращаемого значения метода async. Но поскольку ваш вопросо потреблении асинхронных функций, здесь это не имеет непосредственного отношения.)

В частности, C # 5 будет ожидать, что выражение после ключевого слова await оценител что-то, что вы можете вызвать метод GetAwaiter.(Не имеет значения, предоставляется ли этот метод объектом / структурой, для которой вычисляется выражение, или предоставляется методом расширения.) Вещи, возвращаемые GetAwaiter, должны предлагать два метода: BeginAwait и EndAwait.

Это единственные вызовы методов, которые C # 5 добавит в ваш код при преобразовании его в поддержку async / await.Более того, он не изменит никаких вызовов методов, уже существующих в вашем коде, поэтому, если вы уже вызываете какой-либо метод, скажем, Read, он не избавится от этого или не заменит его.Это только добавляет к тому, что вы уже написали.

Отношение между C # 5 APM (Begin / EndXxx) довольно близко.То, как вы используете APM, заключается в том, что вы сначала оборачиваете работу APM в Task (что вы уже можете сделать сегодня в .NET 4, используя различные перегрузки метода Task.Factory.FromAsync), а затем вы полагаетесь на расширениеметоды, позволяющие использовать Task ключевым словом await.

1 голос
/ 05 ноября 2010

Он переписывает только метод, помеченный async, и превращает только операторы await (которые работают только с типами задач и аналогичными типами результатов) в асинхронное продолжение.

Таким образом, вам потребуется функция, которая возвращает задание (возможно, называется что-то вроде FooTaskAsync, или создать его из пары BeginFoo, EndFoo.

Вызов на обычный Read останется простым синхронным блокирующим вызовом.

...