Разница между 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 всегда немного расплывчато тоже. Я всегда думал, что это, по сути, поток пользовательского интерфейса.
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