2013-11-29 3 views
5

Я не могу понять, требуется ли утверждение ожидания, когда вызов метода асинхронного вызова является последним вызовом в моем асинхронном методе. Например.выполняет последний асинхронный вызов в асинхронном режиме?

public async Task CallAsync(byte[] data) 
{ 
    await Call1Async(data); 
    Call2Async(data); 
} 

public async Task Call1Async(byte[] data) 
{ 
    ... 
} 

public async Task Call2Async(byte[] data) 
{ 
    ... 
} 

Вышеприведенное будет скомпилировано, но с предупреждением «рассмотрите заявку на ожидание этого метода». Но я думаю, что это будет тратить ресурсы на применение, ожидая последнего вызова метода.

В то же время, если я использую return Call2Async(data); вместо Call2Async(data);, предупреждение исчезнет. Это означает, что await на самом деле не требуется в такой ситуации.

Но это работает только для методов, имеющих возвращаемое значение (т. Е. Task<T>, а не только Task). Мне нужно это для методов без возвращаемых значений. Есть ли способ сделать то же самое для возвращающих значение методов?

I.e. Мне нужно как-то вернуть Task объект, возвращенный Call2Async вызывающему абоненту CallAsync, и я не могу использовать оператор return в CallAsync явно, так как мои методы не имеют возвращаемых значений. Конечно, я могу настроить их все, чтобы вернуть значения (например, true), но это не было бы изящным решением.

P.S. Если у меня есть единственный асинхронный вызов в моем методе, я просто не добавляю «async» к сигнатуре метода, и он работает (оператор «return» не требуется). Но если метод содержит более одного асинхронного вызова, мне нужно иметь модификатор «async», чтобы он мог дождаться первого вызова «Ожидать Call1Async (данные)». И добавление модификатора «async» заставляет компилятор требовать «return», чтобы вернуть объект Task к вызывающему (и это работает только для методов с возвращаемыми значениями). Это то, что я пытаюсь преодолеть.

ответ

7

В следующем методе:

public async Task CallAsync(byte[] data) 
{ 
    await Call1Async(data); 
    Call2Async(data); 
} 

управления от возврата метода после начала Call2Async. То есть, если вы должны были await CallAsync(data), он закончил бы до Call2Async. Вероятно, это не то, что вы намеревались. Этот метод завершится только тогда, когда оба вызова завершение:

public async Task CallAsync(byte[] data) 
{ 
    await Call1Async(data); 
    await Call2Async(data); 
} 

Вы можете увидеть разницу в этих примерах выходах (I реализованы два асинхронные называют просто напечатать старт, задержку на секунду, а затем распечатать конец).

void Main() 
{ 
    Console.WriteLine("Main start"); 
    CallAsync(null).Wait(); 
    Console.WriteLine("Main end"); 
} 

Метод без второго await отпечатков:

Main start 
Call1Async start 
Call1Async end 
Call2Async start 
Main end 
Call2Async end 

И с вторым await:

Main start 
Call1Async start 
Call1Async end 
Call2Async start 
Call2Async end 
Main end 

Эта реализация также имеет проблему:

public Task CallAsync(byte[] data) 
{ 
    Call1Async(data); 
    return Call2Async(data); 
} 

Он одновременно запускает оба вызова асинхронного вызова, но затем возвращает управление, когда Call2Async завершает, завершено ли Call1Async или нет. Опять же, это, вероятно, не то, что вы намеревались.

+0

@dcastro, если вы не сделаете 'CallAsync' ' s type 'Task ', вы не можете сделать t hat: либо 1. вы включаете ключевое слово 'async' и можете использовать' await', но в противном случае писать метод, как 'void', или 2. у вас нет' async', нельзя использовать 'await' , а затем верните «Задача» –

+0

@TimS. Спасибо за ответ. Итак, вы подтверждаете, что единственный способ вернуть CallAync к вызывающей стороне ту же задачу, которая возвращается Call2Async, - это сделать все заданные параметры параметрами, например Task , даже если мне не нужно какое-либо возвращаемое значение? – Alex

+1

@Alex Обычно нет необходимости включать фиктивное значение или возвращать 'Задача' Call2Async'. Я бы порекомендовал вам сохранить их просто 'Задача' и использовать оба' await '. Вы, скорее всего, не хотите возвращать 'Задача' Call2Async', но пусть' async' сгенерирует 'Task', который ждет, пока не будут выполнены оба вызова асинхронного вызова. –

0

Ключевое слово async указывает, что метод является асинхронным, и в нем будет содержаться ключевое слово ожидания. Я не понимаю, почему у вас несколько асинхронных методов?

Рассмотрим следующий пример:

async void MyMethod() 
{ 
Task<object> result = MyWorkAsync(); 

MyIndependentOtherWork(); 

object res = await result; 
} 

Вызов MyWorkAsync, как создание нити "Тото", чтобы выполнить метод (т.е. Thread.start (MyWorkAsyn))

Await ключевое слово походит делает Присоедините форму текущего потока к потоку «toto» и получите результат «toto», и в то же время вы получите свою другую независимую работу для выполнения по текущему потоку

+0

«Присоединиться» - это неправильный термин здесь, он не «соединяется» (объединение подразумевает, что один поток ожидает другого), он добавляет продолжение. –

+0

Эти асинхронные методы внутренне вызывают асинхронные сокеты. Например. Call1Async отправляет запрос, а Call2Async получает ответ. – Alex

+0

Правильно, Питер, неправильный выбор слова, ожидание приостановить выполнение метода не текущей нитью – MSE

Смежные вопросы