2017-02-16 5 views
0

Я начал погружаться в aync-программирование, и я хочу выполнить очень простой метод добавления как операцию async.Async полностью на пути к Task.Run по простому методу вычисления

Одна из вещей, которые я прочитал, заключается в том, что действительно асинхронная программа не требует переключения потоков => это означает, что Task.Run(..) можно избежать.

Это, как я реализовал метод добавления:

public class TaskSimpleExample 
    { 
     public static void SimpleCalcExample() 
     { 
      // Will perform in background 
      Task<int> resultTask = Task.Run(() => BeginCalcNumbers(6, 6)); 
      Console.WriteLine("Doing Work"); 
      Console.WriteLine("Doing More Work"); 
      Console.WriteLine("Doing Extra Work"); 
      resultTask.Wait(); 
      Console.WriteLine("Work is done!"); 
     } 

     static int BeginCalcNumbers(int number1, int number2) 
     { 
      int result = Add(number1, number2); 
      Console.WriteLine(result); 
      return result; 
     } 

     static int Add(int number1, int number2) 
     { 
      int result = number1 + number2; 
      return result; 
     } 
    } 

К сожалению, я понимаю, что это не имеет ничего общего с async. Он просто открывает другой поток и работает в фоновом режиме.

Я не смог преобразовать этот код, чтобы использовать async & await (и устранить Task.Run). Является ли это возможным ? (Обратите внимание, что мне нужно продолжить после обратного вызова в другом месте в методе, используя resultTask.Wait()).

+0

Почему вы хотите использовать асинхра/ожидание при добавлении двух чисел? Это кажется излишним. –

+1

Вы не можете избавиться от 'Task.Run', так как ни одна из ваших инструкций не является асинхронной. Таким образом, «Task.Run» - единственное, что вы можете ожидать в этом примере. – Petaflop

+0

@JoakimSkoog, добавляющий к числу, является просто примером для задачи с привязкой к CPU – ohadinho

ответ

4

Что вы знаете о Task.Run абсолютно правильно, и это в значительной степени смысл использования Task.Run

Task.Run Использование выполнит метод на поток пула потоков и возвращает задачу, которая представляет собой завершение метода.

Как говорит Стептен Клири, вы должны использовать Task.Run только для вызова методов с привязкой к ЦП.

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

Вот хороший пример того, как использовать Task.Run правильно:

class MyService 
{ 
    public int CalculateMandelbrot() 
    { 
    // Tons of work to do in here! 
    for (int i = 0; i != 10000000; ++i) 
     ; 
    return 42; 
    } 
} 

... 

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(() => myService.CalculateMandelbrot()); 
} 

Также вы должны прочитать Task.Run Etiquette and Proper Usage и Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation, если вы заинтересованы в получении дополнительной информации о Task.Run

+0

Спасибо за подробный ответ. Можете ли вы объяснить, почему я не могу просто: Task.Run (() => myService.CalculateMandelbrot()); без ключевых слов async & wait? Task.Run запускает фоновый поток, так зачем мне асинхронно и ждут здесь? – ohadinho

+0

Это довольно просто. Во-первых, вам нужно ключевое слово async для использования ключевого слова ожидания и без ключевого слова wait, ваш метод будет запускаться только синхронно, что вы не хотите делать, потому что вы заблокируете поток currecnt (скажем, поток пользовательского интерфейса) в ожидании завершения метода CalculateMandelbrot. Поскольку Task.Run возвращает задачу, ожидая этой задачи, вы должны дождаться завершения вычисления CalculateMandelbrot, не блокируя текущий поток. –

+0

", потому что вы заблокируете текущий поток (скажем, поток пользовательского интерфейса)" Но почему я блокирую поток пользовательского интерфейса, если Task.Run запускает этот процесс в OTHER background thread? – ohadinho