С практическим асинхронным программированием столкнулся относительно недавно, и, изучая тему детальнее, назрел вопрос:
При создании задачи с помощью Task.Factory.StartNew
(с параметром TaskCreationOptions.LongRunning
) поток для задачи выбирается НЕ из пула.
Какой поток выбирается при создании с помощью TaskCompletionSource
- из пула или не из пула?
P.S. Читал, мол, эти два способа эквивалентны... Но хочется разъяснтить очень важную деталь: какой поток выбирается при втором способе?
Никакой.
Task
— это не обязательно «код, бегущий в каком-то потоке». Это не абстракция над методом, бегущем непонятно где. Это лишь формальное обещание когда-либо предоставить результат. Работает ли над этим результатом один поток, несколько, или вообще ни одного — это внутренняя подробность, скрытая внутри Task
'а, и недоступная наблюдателю.
Таски, создаваемые через Task.Run
или TaskFactory.CreateNew
, действительно являются методом, бегущим в том или ином потоке. Но это не является общим свойством всех тасков. Таск имеет право не бежать нигде.
Например, вы можете создать TaskCompletionSource
, запустить таймер, и по приходу таймера завершить задачу. При этом, понятно, ваш таск не будет бежать ни в каком потоке.
Дополнительное чтение по теме: Нет никакого потока (Stephen Cleary, перевод Андрея Часовских).
Класс TaskCompletionSource<T>
- это класс позволяющий создать задачу Task
, которой вы управляете как марионеткой. Ее можно в любой момент сделать успешно завершившейся или записать в нее исключение и тем самым сказав, что она завершилась с ошибкой. Данный класс можно применять, например, при переводе с паттерна IAsyncResult
на TAP
.
public static Task<IPHostEntry> GetHostEntryAsync(string hostNameOrAddress)
{
var tcs = new TaskCompletionSource<IPHostEntry>();
Dns.BeginGetHostEntry(hostNameOrAddress, asyncResult =>
{
try
{
IPHostEntry result = Dns.EndGetHostEntry(asyncResult);
tcs.SetResult(result);
}
catch(Exception e)
{
tcs.SetException(e);
}
}, null);
return tcs.Task;
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Как связать WPF с EF Core Sqlite и что прописывать в appconfig? Если нельзя связать
Здравствуйте, назрел вопрос по передаче параметров в отчет
У меня есть два паршала, в одном список, а в другом открываеться более детальная информация после того как нажать на запись в спискеКогда...