Как я могу одновременно выполнить два метода, используя асинхронный режим, и дождаться, пока 1 метод finalize продолжит работу с другим?
public class Foo{
public async Task<string> Method1()
{
//run a task
return result;
}
public async void Method2(string result)
{
//do some work
//do some work
//do some work
//wait for method1
//do something with result
}
}
Foo foo = new Foo();
var result = await foo.Method1();
foo.Method2(result);
Ваш вопрос на самом деле противоречив. Вы говорите, что хотите выполнить два метода "сразу" (параллелизм), но затем вы говорите, что хотите дождаться завершения первого (сериализованного). Кроме того, зачем использовать async/await
?
@MickyD Противоречиво? Это довольно простой способ одновременного выполнения работы: «Я буду выполнять эту работу, пока вы выполняете эту работу, и я дам вам знать, как только мне понадобятся ваши результаты» (фактически, код в ответе Теодора Зулиаса — это то, что предлагается в MIcrosoft Документы для смешивания параллелизма с асинхронностью) TPL здесь не требуется, это правильно, но что, если Method1
выполняет асинхронную работу?
@CamiloTerevinto Возможно. Я бы сказал, что это полупараллелизм с добавленным логическим продолжением
Следуя вашему примеру, где Method1 и Method2 вызываются отдельно (Method2 не знает о Method1), вы получите желаемое поведение, передав Task
Method1 методу Method2.
public class Service
{
public async Task<string> MethodOne()
{
// do something
var result = await CalculateSomeResult();
return result;
}
public async Task MethodTwo(Task<string> task)
{
// do some work
// do some work
var methodOneResult = await task;
// do something with the result of methodOne
}
}
Применение
var service = new Service();
var methodOneTask = service.methodOne();
await service.MethodTwo(methodOneTask);
На самом деле это еще один хороший подход (с небольшой проблемой, что код не компилируется из-за async void
, как указал @CamiloTerevinto). Это немного более гибко, чем объединение вызова Method1
непосредственно в Method2
, как это предлагается в принятом ответе.
@CamiloTerevinto, это была слепая копия вопроса ОП, я предполагал, что асинхронные методы никогда не имеют подписи void
.
Если я вас правильно понял, вам нужен Method2 для использования результатов, возвращаемых Method1 - при этом вам нужно вызывать Method2 изнутри Method1, а не после него:
public class Foo{
public async Task<string> Method1()
{
//run a task
return result;
}
public async void Method2(string result)
{
//do some work
//do some work
//do some work
var intermediaryResult = await Method1();
//do something with result
}
}
Foo foo = new Foo();
await foo.Method2(result);
(Кроме того, вам также нужно ждать Method2 - они оба асинхронны)
Кстати, вы должны никогда не используйте асинхронные методы void, если у вас нет выбора - поэтому вместо этого Method2 должен возвращать Task.
Этот код не имеет смысла. Почему объявлен Method2 Method2(string result)
? Почему вы использовали await foo.Method2(result);
, если Method2 — это async void
?
@CamiloTerevinto Я до сих пор не уверен, чего пытается достичь OP, поэтому я бы предпочел дождаться разъяснений, а не пытаться угадать, что исправить :)
Ответ @TheodorZoulias имеет для меня большой смысл, и для OP потребуется крайне неправильно заданный вопрос, чтобы он не хотел того, что показывает этот ответ.
Как насчет этого?
public async Task<string> Method2()
{
//do some work
//do some work
//do some work
var result = await foo.Method1();
//do something with result
return result;
}
Foo foo = new Foo();
var result = await foo.Method2();
Для (полу)параллельного выполнения:
public async Task<string> Method2()
{
var task1 = foo.Method1();
//do some work
//do some work
//do some work
var result = await task1;
//do something with result
return result;
}
Постановка проблемы @Camilo OP предполагает, что желательно последовательное выполнение, тем более что OP, похоже, хочет, чтобы результат метода 1 использовался в методе 2.
@ Камило Теревинто, ты прав. Я обновил свой ответ.
@Джон Это совсем не то, что я понимаю из //wait for method1
, но давайте позволим ОП решить
public class Foo
{
public async Task<string> Method1()
{
//run a task
return result;
}
public async void Method2(string result)
{
//do some work
//do some work
//do some work
//wait for method1
//do something with result
}
}
await Task.Run(()=>
{
Foo foo = new Foo();
var result = foo.Method1();
foo.Method2(result);
});
Вы можете использовать EventWaitHandle
:
public class Sequence {
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset);
public async Task Tsk1() {
Console.WriteLine("Did some work from tsk1");
handle.Set();
}
public async Task Tsk2() {
handle.WaitOne();
Console.WriteLine("Doing work after tsk1 finished");
//do some other stuff
}
}
class Program {
static async Task Main(string[] args) {
Sequence seq = new Sequence();
var t2 =Task.Run(seq.Tsk2);
var t1 =Task.Run(seq.Tsk1);
await Task.WhenAll(t1, t2);
Console.WriteLine("finished both");
}
}
Примечание: async void обычно считается очень плохой идеей.