Разница между TPL & async/await (обработка потоков)



пытаясь понять разницу между TPL & async/await когда дело доходит до создания потока.



я считаю, что ОСАГО (TaskFactory.StartNew) работает аналогично ThreadPool.QueueUserWorkItem в том, что он ставит в очередь работу над потоком в пуле потоков. Это конечно, если вы не используете TaskCreationOptions.LongRunning, который создает новый поток.



я думал async/await будет работать точно так по существу:



TPL:



Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith(
(antecedent) => {
DoSomeWorkAfter();
},TaskScheduler.FromCurrentSynchronizationContext());


Async/Await:



await DoSomeAsyncWork();  
DoSomeWorkAfter();


будут идентичны. Из того, что я читал, кажется, что async/await только "иногда" создает новый поток. Итак, когда он создает новый поток и когда он не создает новый поток? Если бы вы имели дело с портами завершения ввода-вывода, я вижу, что ему не нужно создавать новый поток, но в противном случае я бы подумал, что это нужно. Я думаю, мое понимание FromCurrentSynchronizationContext всегда немного расплывчато тоже. Я всегда думал, что это, по сути, поток пользовательского интерфейса.

868   2  

2 ответов:

я считаю, что TPL (TaskFactory.Startnew) работает аналогично ThreadPool.QueueUserWorkItem в том, что он ставит в очередь работу над потоком в пуле потоков.

очень много.

из того, что я читал, кажется, что async/await только "иногда" создает новый поток.

на самом деле, это никогда не делает. Если вы хотите многопоточность, вы должны реализовать себя. Есть новый Task.Run метод, который является сокращением для Task.Factory.StartNew, и это, вероятно, самый распространенный способ запуска задачи в пуле потоков.

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

Бинго. Так что методы, как Stream.ReadAsync будет на самом деле создать Task обертка вокруг IOCP (если Stream имеет IOCP).

вы также можете создать некоторые номера-ввода/вывода, а не процессора "задачи." Простой пример Task.Delay, который возвращает задачу, которая завершается через некоторое время.

крутая вещь о async/await это то, что вы можете поставить в очередь некоторые работы в пул потоков (например,Task.Run), выполните некоторые операции ввода-вывода (например,Stream.ReadAsync), и сделать некоторые другие операции (например, Task.Delay)... и это все задачи! Их можно ожидать или использовать в таких комбинациях, как Task.WhenAll.

любой метод, который возвращает Task может быть awaited-это не должно быть Ан async метод. Так что Task.Delay и операции ввода/вывода с привязкой просто использовать TaskCompletionSource чтобы создать и завершить задачу-единственное, что делается в пуле потоков, - это фактическое завершение задачи при наступлении события (тайм-аут, завершение ввода-вывода и т. д.).

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

я писал статьи on SynchronizationContext. Наиболее в то время,SynchronizationContext.Current:

  • является контекстом пользовательского интерфейса, если текущий поток является потоком пользовательского интерфейса.
  • является ASP.NET контекст запроса, если текущий поток обслуживает ASP.NET просьба.
  • является контекстом пула потоков в противном случае.

какие-нить можете установить собственную SynchronizationContext, так что есть исключения из правил выше.

обратите внимание, что по умолчанию Task ожидающий будет планировать оставшуюся часть async метод на текущий SynchronizationContextесли это не null; в противном случае он идет на ток TaskScheduler. Сегодня это не так важно, но в ближайшем будущем это будет важным отличием.

я написал свой собственный async/await интро на моем блоге, и Стивен Тоуб недавно опубликовал отличный async/await часто задаваемые вопросы.

что касается " параллелизма "и " многопоточности", см. это связано так вопрос. Я бы скажи async включает параллелизм, который может быть или не быть многопоточным. Это простой в использовании await Task.WhenAll или await Task.WhenAny для параллельной обработки, и если вы явно не используете пул потоков (например,Task.Run или ConfigureAwait(false)), то вы можете иметь несколько одновременных операций в то же время (например, несколько ввода-вывода или других типов, таких как Delay) - и нет никакой нити, необходимой для них. Я использую термин "однопоточный параллелизм" для такого сценария, хотя в ASP.NET хозяин, вы можете на самом деле в конечном итоге с "ноль-резьбовые параллелизма". Что довольно мило.

async / await в основном упрощает ContinueWith методы (продолжение в Продолжение Прохождения Стиле)

он не вводит параллелизм - вам все равно придется сделать это самостоятельно ( или использовать асинхронную версию метода framework. )

Итак, версия C# 5 будет:

await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();

Comments

    Ничего не найдено.