2015-06-29 2 views
1

В этом example от Microsoft, метод имеет тип возвращаемого Task<int>Почему некоторые методы требуют асинхронных возвращаемый тип задачи, а другие не

Пример 1:

async Task<int> AccessTheWebAsync() 
{ 
    // You need to add a reference to System.Net.Http to declare client. 
    HttpClient client = new HttpClient(); 

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents). 
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); 

    // You can do work here that doesn't rely on the string from GetStringAsync. 
    DoIndependentWork(); 

    // The await operator suspends AccessTheWebAsync. 
    // - AccessTheWebAsync can't continue until getStringTask is complete. 
    // - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    // - Control resumes here when getStringTask is complete. 
    // - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask; 

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length; 
} 

В этом второй пример, он использует async и ждет, НО не возвращает тип задачи <>, почему?

Пример 2:

namespace ConsoleApplication 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ReadCharacters(); 
     } 

     static async void ReadCharacters() 
     { 
      String result; 
      using (StreamReader reader = File.OpenText("existingfile.txt")) 
      { 
       Console.WriteLine("Opened file."); 
       result = await reader.ReadToEndAsync(); 
       Console.WriteLine("Contains: " + result); 
      } 
     } 
    } 
} 

В-третьих, в первом примере, можно возвращать массив (строк)?

ответ

6

В этом втором примере, он использует асинхра и ждет, НО не возвращает типа задачи <>, почему?

Они сделали ошибку. Всякий раз, когда вы создаете метод, который является асинхронным и не имеет возвращаемого значения , он должен вернуть Task. Единственное исключение - обработчики событий, где вам необходимо поддерживать совместимость с подписью делегатов, но это не так. Подумайте о Task как эквивалент асинхронных методов void.

Почему вы на самом деле хотите, чтобы вернуть Task, а не void? Поскольку возврат Task позволяет отслеживать состояние выполнения, а также позволяет корректно обрабатывать любые исключения, инкапсулированные внутри текущей операции.

Например, думать о async void метод, который бросает:

public async void WaitAndThrowAsync() 
{ 
    await Task.Delay(1000); 
    throw new Exception("yay"); 
} 

public void CallWaitAndThrowAsync() 
{ 
    // What happens when it throws here? 
    WaitAndThrowAsync(); 
} 

При вызове этого, вы не имеете никакого способа фактически обрабатывать исключения, происходящие внутри метода, это «огонь и забыть» для вызова -site. Но когда вы открыли Task, теперь вы можете лучше справиться с этим исключение, асинхронно в режиме ожидания:

public async Task WaitAndThrowAsync() 
{ 
    await Task.Delay(1000); 
    throw new Exception("yay"); 
} 

public async Task CallWaitAndThrowAsync() 
{ 
    try 
    { 
     await WaitAndThrowAsync(); 
    } 
    catch (Exception e) 
    { 
     // Do something. 
    } 
} 

В-третьих, в первом примере, можно вернуть массив (строк)?

Да, возвращая Task<string[]>:

public async Task<string> GetArrayAsync() 
{ 
    HttpClient client = new HttpClient(); 
    var responseStream = await client.GetStreamAsync("http://msdn.microsoft.com"); 

    using (var streamReader = new StreamReader(responseStream)) 
    { 
     return await streamReader.ReadToEndAsync(); 
    } 
} 

Когда вы отмечаете метод async, компилятор неявно создать Task для вас. Когда у вас есть тип возврата, сгенерированная задача - это Task<T>, где T - ваш тип возврата.

+0

Итак, правильная практика всегда возвращает тип задачи <>? Как вы исправите пример выше? –

+0

@Nexusfactor Правильная практика говорит, что возвращает «Задача», когда у вас нет фактического значения для возврата из метода, и используйте «Задача », когда у вас действительно есть значение для возврата из метода. –

+0

MethodthatreturnsArrayAsync действительно будет ReadToEndAsync(), правильно? –

0

Это второй не по guidelines specified by Microsoft:

Возвращение тип один из следующих типов: - Задача, если ваш метод имеет возвращаемое заявление, в котором операнд имеет тип TResult. - Задача, если у вашего метода нет оператора return или есть оператор return без операнда. - Void (Sub в Visual Basic), если вы пишете обработчик событий async.

Почему методы должны возвращать Task или Task<T>?

Каждая возвращенная задача представляет собой текущую работу. Задача инкапсулирует информацию о состоянии асинхронного процесса и, в конечном итоге, либо конечный результат процесса, либо исключение, которое процесс поднимает, если он не выполняется.

Таким образом, вы теряете информацию, когда используете void. Вы отбрасываете фактическую информацию о ходе выполнения и исполнении. Поэтому для возвращаемого типа void используйте Task. Для любого другого типа используйте Task<T>, где T является фактическим типом возврата.

Некоторые методы могут возвращать void, но это запрещено обработчик события или стартерных методов:

Метод асинхронной также может быть Суб метод (Visual Basic) или иметь тип возвращаемого недействительным (C#). Этот тип возврата используется в основном для определения обработчиков событий, где требуется тип возврата void. Асинхронные обработчики событий часто служат отправной точкой для асинхронных программ.

1

Второй пример не является хорошим примером: с async void больше не возможно ожидать асинхронного метода. async void должен использоваться только для обработчиков событий.

Для вашего второго вопроса да, возможно вернуть массив строк. Просто используйте Task<string[]>.

Я очень рекомендую вам прочитать эту прекрасную статью из Stephen Cleary: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

Некоторых лучших практики из статьи:

  • Избегайте асинхронную пустоту: Предпочитают методы задач асинхронных над асинхронными недействительными методами. Исключения: обработчики событий
  • Async полностью: не смешивайте блокировку и асинхронный код. Исключения: Основной метод консоли
Смежные вопросы