TPL TaskFactory.FromAsync vs Задачи с методами блокировки - PullRequest
20 голосов
/ 16 февраля 2011

Мне было интересно, есть ли какие-либо последствия для производительности между использованием TPL TaskFactory.FromAsync и использованием TaskFactory.StartNew на блокирующих версиях методов.Я пишу TCP-сервер, который будет поддерживать не более 100 одновременных подключений.После написания кода с первой опцией и объединения нескольких операций чтения и записи с продолжением, я остался уродливым, трудным для отладки кода.

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

Например,Существуют ли различия в производительности между этими двумя вызовами:

NetworkStream stream;
byte[] data;
int bytesRead;

//using FromAsync
Task<int> readChunk = Task<int>.Factory.FromAsync (
      stream.BeginRead, stream.EndRead,
      data, bytesRead, data.Length - bytesRead, null);

//using StartNew with blocking version
Task<int> readChunk2 = Task<int>.Factory.StartNew(() => 
      stream.Read(data, bytesRead, data.Length - bytesRead));

Ответы [ 2 ]

45 голосов
/ 22 февраля 2011

Вы абсолютно хотите использовать FromAsync, когда API предлагает версию метода BeginXXX / EndXXX. Разница в том, что в случае чего-то вроде Stream или Socket или WebRequest вы фактически будете использовать асинхронный ввод-вывод под крышками (например, порты завершения ввода-вывода в Windows), что далеко более эффективно, чем блокирование нескольких потоков ЦП, выполняющих синхронную операцию. Эти методы обеспечивают лучший способ достижения масштабируемости ввода / вывода.

Ознакомьтесь с этим разделом .NET SDK для MSDN, озаглавленным TPL и традиционное .NET для асинхронного программирования , чтобы получить дополнительную информацию о том, как объединить эти две модели программирования для достижения асинхронной нирваны.

4 голосов
/ 29 апреля 2011

После копии с внешней ссылки:

Да. В .NET 4 библиотека параллельных задач включает встроенную оболочку для шаблона APM (начало / конец): Task.Factory.FromAsync. Например, если вы хотите создать задачу для звонка в Stream Метод BeginRead / EndRead, вы можете сделать:

Stream s = ...;
byte [] buffer = ...;
Task<int> numBytesRead = Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);
// or with await
int numBytesRead = await Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);

Under the covers, FromAsync is just built on top of TaskCompletionSource<TResult>.  A simple version of FromAsync for this read example would look something like:

var tcs = new TaskCompletionSource<TResult>();
s.BeginRead(buffer, 0, buffer.Length, iar =>
{
    try { tcs.SetResult(s.EndRead(iar)); }
    catch(Exception exc) { tcs.SetException(exc); }
}, null);
Task<int> numBytesRead = tcs.Task;

http://social.msdn.microsoft.com/Forums/en/async/thread/ed8a14e8-d19a-42d1-bc3f-7017bdfed09c

...