У меня есть вопрос о том, как настраиваются новые ключевые слова async
/await
и класс Task
в С# 4.5.
Прежде всего, я задумался над моей проблемой: я разрабатываю структуру с помощью следующего дизайна:
- В одном потоке есть список "текущих действий" (обычно от 100 до 200 элементов), которые хранятся в виде собственной структуры данных и хранятся в виде списка. Он имеет функцию
Update()
, которая перечисляет список и проверяет, нужно ли выполнять какие-либо "вещи" и делает это. В основном это похоже на большой планировщик потоков. Чтобы упростить ситуацию, допустим, что "вещи, которые нужно сделать" - это функции, которые возвращают booleantrue
, когда они "закончены" (и не должны вызываться следующим Update) иfalse
, когда диспетчер должен снова вызвать их следующее обновление. - Все "вещи" не должны запускаться одновременно, а также должны выполняться в этом одном потоке (из-за статических переменных потока)
- Есть и другие темы, которые делают другие вещи. Они структурированы таким же образом: Big loop, который выполняет итерацию нескольких вещей hundret в большой функции
Update()
. - Темы могут отправлять друг другу сообщения, в том числе "удаленные вызовы процедур". Для этих удаленных вызовов система RPC возвращает какой-то будущий объект в значение результата. В другом потоке вставлена новая "вещь, которую нужно сделать".
- Общей "вещью" является просто последовательность RPC, соединенных вместе. В настоящий момент синтаксис этой "цепочки" очень многословен и сложен, поскольку вам нужно вручную проверить состояние завершения предыдущих RPC и вызвать следующие и т.д.
Пример:
Future f1, f2;
bool SomeThingToDo() // returns true when "finished"
{
if (f1 == null)
f1 = Remote1.CallF1();
else if (f1.IsComplete && f2 == null)
f2 = Remote2.CallF2();
else if (f2 != null && f2.IsComplete)
return true;
return false;
}
Теперь этот звук, похожий на async
и await
на С# 5.0, может помочь мне здесь. Я не на 100% полностью понимаю, что он делает под капотом (какие-либо хорошие ссылки?), Но, как я понял из нескольких разговоров, которые я наблюдал, он точно делает то, что я хочу, с помощью этого красиво простого кода:
async Task SomeThingToDo() // returning task is completed when this is finished.
{
await Remote1.CallF1();
await Remote2.CallF2();
}
Но я не могу найти способ написать мою функцию Update()
, чтобы сделать что-то подобное. async
и await
похоже, хотят использовать класс Task
, который, в свою очередь, кажется, нуждается в реальных потоках?
Мое ближайшее "решение":
Первый поток (который работает SomeThingToDo
) вызывает свои функции только один раз и сохраняет возвращенную задачу и тесты на каждом Update()
, завершена ли задача.
Remote1.CallF1
возвращает новую задачу с пустым значением параметра "Действие как конструктор" и запоминает возвращаемую задачу. Когда F1 фактически завершена, он вызывает RunSynchronously()
в задаче, чтобы пометить ее как завершенную.
Мне кажется, как извращение системы задач. А рядом с ним создается разделяемая память (Task IsComplete
boolean) между двумя потоками, которые я бы хотел заменить нашей удаленной системой обмена сообщениями, если это возможно.
Наконец, это не решает мою проблему, так как она не работает с реализацией, подобной ожиданию SomeThingToDo
выше. Кажется, автоматически созданные объекты задачи, возвращаемые функцией async, немедленно завершаются?
Итак, наконец, мои вопросы:
- Можно ли подключиться к async/await для использования моих собственных реализаций вместо
Task<T>
? - Если это невозможно, могу ли я использовать
Task
без каких-либо действий, связанных с "блокировкой" и "потоками"? - Любая хорошая ссылка, что именно происходит, когда я пишу
async
иawait
?