sobota, 10 listopada 2012

await, async - konwencje i fakty

Nietypowo, na początek trochę kodu:

Code:
        public async Task<int> GetDataLengthAsync()
        {
            var client = new HttpClient();
            var taskResult = client.GetStringAsync("http://onet.pl");
            DoSomeStaff();
            var pageContent = await taskResult;

            return pageContent.Length; 
        }

        private void DoSomeStaff()
        {
            Console.WriteLine("Doing something");
        }

Co czyni powyższą metodę asynchroniczną?
  • sygnatura metody zawiera słowo kluczowe async
  • nazwa metody zawiera przyrostek Async
  • typ zwracany to:
    • Task<TResult>
    • Task
    • void
  • metoda zawiera przynajmniej jedno słowo kluczowe await
.NET 4.5 zawiera wiele metod asynchronicznych i poznać je możemy właśnie po przyrosku Async. 

Fakty związane z async i await:

  • Należy pamiętać że await nie tworzy nowego wątku. Jeżeli chcemy, aby został stworzony nowy wątek można skorzystać z nowej metody Task.Run, która jest skrótem od Task.Factory.StartNew.
  • Jeżeli metoda nie zawiera, żadnego słowa kluczowego await, będzie wykonywana tak jak zwykła metoda synchroniczna. Ze strony kompilatora zostanie zgłoszone jedynie ostrzeżenie o takim fakcie. 
  • Jeżeli metoda zwraca Task dostajemy informację o stanie zadania, rezultat bądź też wyjątek co poszło nie tak podczas wykonywania naszego kodu.
  • Metoda async nie może przyjmować parametrów przekazywanych przez referencję (ref). Może jednak w sobie wywoływać metody, przyjmujące parametry w ten sposób.

4 komentarze:

  1. Mała uwaga co do tytułu powinno być acync zamiast asynch.

    OdpowiedzUsuń
  2. Interesujące.
    Tylko mam wątplikowości co się stanie gdy osiągniemy await, a GetStringAsync nie zakończyło się jeszcze?
    Co wtedy zwróci funckja GetDataLengthAsync?

    OdpowiedzUsuń
    Odpowiedzi
    1. Nastąpi oczekiwanie na rezultat. Powyższe można by zapisać w następujący sposób:

      var newTask = new Task(() => 20);
      newTask.Start();
      newTask.ContinueWith(new Action(task1 => { int a = 20; }),
      TaskScheduler.FromCurrentSynchronizationContext());


      Tak więc await można traktować jak ContinueWith.

      Usuń