Ожидание async/ожидание внутри задачи
У меня есть эта конструкция в моей main()
, которая создает
var tasks = new List<Task>();
var t = Task.Factory.StartNew(
async () =>
{
Foo.Fim();
await Foo.DoBar();
});
//DoBar not completed
t.Wait();
//Foo.Fim() done, Foo.DoBar should be but isn't
Однако, когда я .Wait
для t, он не будет ждать завершения вызова DoBar()
.
Как я могу заставить его ждать?
Ответы
Ответ 1
Не рекомендуется использовать Task.Factory.StartNew
с async-await
, вместо этого следует использовать Task.Run
:
var t = Task.Run(
async () =>
{
Foo.Fim();
await Foo.DoBar();
});
Task.Factory.StartNew
api был создан до асинхронного шаблона (TAP) на основе задач и async-await
. Он вернет Task<Task>
, потому что вы запускаете задачу с выражением лямбда, которое является асинхронным, и поэтому возвращает задачу. Unwrap
будет извлекать внутреннюю задачу, но Task.Run
будет неявно делать это для вас.
Для более глубокого сравнения всегда есть соответствующая статья Стивена Туба: Task.Run vs Task.Factory.StartNew
Ответ 2
Кажется, что я получаю желаемую функциональность Unwrap()
задачи.
Я не совсем уверен, что я объясню это, но я полагаю, что это работает.
var t = Task.Factory.StartNew(
async () =>
{
Foo.Fim();
await Foo.DoBar();
}).Unwrap();
edit: Я искал ddescription Unwrap()
:
Creates a proxy Task that represents the asynchronous operation of a Task<Task<T>>
Я думал, что это традиционно, что делала эта задача, но если мне нужно вызвать разворот, я полагаю, что это хорошо.
Ответ 3
Недавно я столкнулся с подобной проблемой и выяснил, что все, что вам нужно сделать, это DoBar()
вернуть некоторое значение и использовать .Result вместо wait.
var g = Task.Run(() => func(arg));
var val = g.Result;
Это будет ждать, пока func
вернет свой вывод и назначит его val.