AFAIK, все, что он знает, - это то, что в какой-то момент вызывается его метод SetResult
или SetException
метод для завершения Task<T>
экспонирования через его Task
свойство.
Другими словами, он выступает в качестве производителя для Task<TResult>
и его завершения.
Я видел здесь пример:
Если мне нужен способ выполнить Func асинхронно и иметь задачу для представления этой операции.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Который может быть использован *, если у меня не было Task.Factory.StartNew
- но у меня есть Task.Factory.StartNew
.
Вопрос:
Может кто - то пожалуйста , объясните на примере сценарий , связанный непосредственно с , TaskCompletionSource
а не к гипотетической ситуации , в которой у меня нет Task.Factory.StartNew
?
c#
.net
.net-4.0
task-parallel-library
taskcompletionsource
Ройи Намир
источник
источник
Ответы:
Я в основном использую его, когда доступен только API, основанный на событиях ( например, сокеты Windows Phone 8 ):
Так что это особенно полезно, когда используется вместе с
async
ключевым словом C # 5 .источник
SomeApiWrapper
, чего ждут где-нибудь, пока издатель не поднимет событие, которое заставит эту задачу завершиться?Microsoft.Bcl.Async
пакет для NuGet, который позволяет использоватьasync/await
ключевые слова в проектах .NET 4.0 (рекомендуется VS2012 и выше).По моему опыту,
TaskCompletionSource
отлично подходит для упаковки старых асинхронных шаблонов в современныеasync/await
шаблон.Самый полезный пример, который я могу вспомнить, - это работа с
Socket
. У него есть старые шаблоны APM и EAP, но нетawaitable Task
методов, которыеTcpListener
иTcpClient
есть.У меня лично есть несколько проблем с
NetworkStream
классом, и я предпочитаю сырьеSocket
. Поскольку я также люблюasync/await
шаблон, я создал класс расширения,SocketExtender
который создает несколько методов расширенияSocket
.Все эти методы используют,
TaskCompletionSource<T>
чтобы обернуть асинхронные вызовы следующим образом:Я передаю
socket
вBeginAccept
методы, так что я получаю небольшое повышение производительности от компилятора, которому не нужно поднимать локальный параметр.Тогда красота всего этого:
источник
Begin.. End...
операторы.Для меня классический сценарий использования
TaskCompletionSource
- это когда возможно, что мой метод не обязательно должен выполнять длительную операцию. Это позволяет нам выбирать конкретные случаи, когда мы хотели бы использовать новый поток.Хороший пример для этого, когда вы используете кеш. У вас может быть
GetResourceAsync
метод, который ищет в кэше запрошенный ресурс и сразу же возвращает (не используя новый поток, используяTaskCompletionSource
), если ресурс был найден. Только если ресурс не найден, мы хотели бы использовать новый поток и получить его с помощьюTask.Run()
.Пример кода можно посмотреть здесь: Как условно выполнить код асинхронно с помощью задач
источник
Task.FromResult
для этого. Конечно, если вы используете 4.0 и у вас нет того, дляTask.FromResult
чего вы должны использовать TCS, это написать свой собственныйFromResult
.Task.FromResult
доступен только с .NET 4.5. До этого это был способ добиться такого поведения.Task.Run
, указывая, что это 4.5+. И мой предыдущий комментарий специально адресован .NET 4.0.В этом сообщении в блоге Леви Ботелхо описывает, как использовать
TaskCompletionSource
для написания асинхронной оболочки для Процесса, чтобы вы могли запустить его и дождаться его завершения.и его использование
источник
Похоже, никто не упомянул, но я думаю, что юнит-тесты тоже можно считать реальной жизнью .
Я считаю
TaskCompletionSource
полезным при насмешке зависимости с помощью асинхронного метода.В реальной тестируемой программе:
В модульных тестах:
В конце концов, такое использование TaskCompletionSource кажется еще одним случаем «объекта Task, который не выполняет код».
источник
TaskCompletionSource используется для создания объектов Task, которые не выполняют код. В реальных сценариях TaskCompletionSource идеально подходит для операций ввода-вывода. Таким образом, вы получаете все преимущества задач (например, возвращаемые значения, продолжения и т. Д.), Не блокируя поток на время выполнения операции. Если ваша «функция» связана с операциями ввода-вывода, не рекомендуется блокировать поток с помощью новой задачи . Вместо этого, используя TaskCompletionSource , вы можете создать подчиненную задачу, чтобы просто указать, когда ваша связанная операция ввода-вывода завершается или происходит сбой.
источник
В этом посте приведен реальный пример с достойным объяснением из блога «Параллельное программирование с .NET» . Вы действительно должны прочитать это, но вот резюме в любом случае.
В сообщении блога показаны две реализации:
Первая показанная реализация основана на
Task<>
двух основных недостатках и имеет их. Во втором посте о внедрении они смягчаются с помощьюTaskCompletionSource<>
.Вот эта вторая реализация:
источник
await Task.Delay(millisecondsDelay); action(); return;
или (в .Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Это может быть упрощением, но источник TaskCompletion позволяет ожидать события. Поскольку tcs.SetResult устанавливается только при возникновении события, вызывающая сторона может ожидать выполнения задачи.
Посмотрите это видео, чтобы узнать больше:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
источник
Я в реальном мире сценарий, где я использовал
TaskCompletionSource
при реализации очереди загрузки. В моем случае, если пользователь запускает 100 загрузок, я не хочу запускать их все сразу, и вместо того, чтобы возвращать объявленную задачу, я возвращаю задачу, к которой прикрепленTaskCompletionSource
. После завершения загрузки поток, работающий в очереди, завершает задачу.Ключевой концепцией здесь является то, что я отделяюсь, когда клиент запрашивает запуск задачи с момента ее фактического запуска. В этом случае, потому что я не хочу, чтобы клиенту приходилось иметь дело с управлением ресурсами.
обратите внимание, что вы можете использовать async / await в .net 4, если вы используете компилятор C # 5 (VS 2012+), смотрите здесь для получения дополнительной информации.
источник
Я использовал
TaskCompletionSource
для запуска задачи, пока она не будет отменена. В этом случае это подписчик ServiceBus, который я обычно хочу запускать до тех пор, пока приложение работает.источник
TaskCompletionSource
Задачи, какWaitHandle
темы. И поэтому мы можем использоватьTaskCompletionSource
для выполнения точной сигнализации .Примером является мой ответ на этот вопрос: задержка ContentDialog после нажатия кнопки ОК
источник