2014-04-25 16 views
22

W jednym z filmów MVA widziałem następny budowy:Jak czekają na async delegata

static void Main(string[] args) 
{ 
    Action testAction = async() => 
    { 
     Console.WriteLine("In"); 
     await Task.Delay(100); 
     Console.WriteLine("First delay"); 
     await Task.Delay(100); 
     Console.WriteLine("Second delay"); 
    }; 
    testAction.Invoke(); 
} 

wyniku realizacji będą:

In 
Press any key to continue . . . 

Jest doskonale kompiluje, ale teraz ja nie zobacz jakikolwiek sposób na to czekać. Po wywołaniu mogę wstawić Thread.Sleep lub Console.ReadKey, ale tego nie chcę.

Więc jak to delegat powinien zostać zmodyfikowany tak, aby stać się awaitable? (Lub przynajmniej jak mogę śledzić że wykonanie zakończone?)

Czy są jakieś praktyczne wykorzystanie takich delegatów?

+4

Nie ma mowy, aby 'await' go. Jeśli był to "Func ", byłby inny. Dlatego należy unikać 'async void' i najlepiej używać go tylko w procedurach obsługi zdarzeń najwyższego poziomu *. –

+2

Możesz znaleźć [mój post na blogu na temat 'async' delegatów] (http://blog.stephencleary.com/2014/02/synchronous-and-asynchronous-delegate.html) pomocne. –

Odpowiedz

39

Aby coś być oczekiwany, to musi być awaitable. Ponieważ nie jest to void, nie możesz czekać na każdego delegata Action.

awaitable jest dowolnego typu, który implementuje GetAwaiter metody, która zwraca typu, który realizuje zarówno INotifyCompletion lub ICriticalNotifyCompletion, jak Task i Task<T>, na przykład.

Jeśli chcesz czekać na delegata, użyj Func<Task>, która jest równoważna nazwie metody z następującym podpisem:

public Task Func() 

So, w oczekiwaniu, zmienić metodę:

static void Main(string[] args) 
{ 
    Func<Task> testFunc = async() => 
    { 
     Console.WriteLine("In"); 
     await Task.Delay(100); 
     Console.WriteLine("First delay"); 
     await Task.Delay(100); 
     Console.WriteLine("Second delay"); 
    }; 
} 

A teraz można go czeka:

await testFunc(); 
Powiązane problemy