2012-10-21 11 views
27
public class test 
{ 
    public async Task Go() 
    { 
     await PrintAnswerToLife(); 
     Console.WriteLine("done"); 
    } 

    public async Task PrintAnswerToLife() 
    { 
     int answer = await GetAnswerToLife(); 
     Console.WriteLine(answer); 
    } 

    public async Task<int> GetAnswerToLife() 
    { 
     await Task.Delay(5000); 
     int answer = 21 * 2; 
     return answer; 
    } 
} 

jeśli chcę zadzwonić pójść w metodzie main(), jak mogę to zrobić? Próbuję C# nowe funkcje, wiem, że mogę podłączyć metodę asynchroniczną do zdarzenia i przez wywołanie tego zdarzenia, można wywołać metodę async.Jak mogę wywołać metodę async Go na przykład Main()?

Ale co, jeśli chcę wywołać ją bezpośrednio w metodzie głównej? Jak mogę to zrobić?

zrobiłem coś

class Program 
{ 
    static void Main(string[] args) 
    { 
     test t = new test(); 
     t.Go().GetAwaiter().OnCompleted(() => 
     { 
      Console.WriteLine("finished"); 
     }); 
     Console.ReadKey(); 
    } 


} 

Ale wydaje się, że to martwy blokady i nic nie jest drukowane na ekranie.

+0

wydaje mi się znaleźć problem, bo GetAwaiter() OnCompleted() powróci do natychmiastowa główna funkcja, więc gdy wywoływana jest funkcja Console.Readkey(), główny wątek blokuje, dlatego komunikat wyjściowy zwrócony z zadania nie może zostać wydrukowany na ekranie, ponieważ oczekuje na odblokowanie głównego wątku. Jeśli zamieniam Console.readkey() na while (true) { Thread.Sleep (1000); } działa poprawnie. – Larry

+0

Nie mogę odtworzyć problemu z zakleszczeniem, ale jeśli ktoś ma na to ochotę, użyj 'Go(). ConfigureAwait (false) .GetAwaiter()', aby użyć nowego kontekstu w metodzie asynchronicznej. – arviman

Odpowiedz

39

Twoja metoda Main można uprościć:

static void Main(string[] args) 
{ 
    test t = new test(); 
    t.Go().Wait(); 
    Console.WriteLine("finished"); 
    Console.ReadKey(); 
} 

Jest to część pięknem async hasła (i związane z funkcjonalnością): wykorzystanie i mylące charakter wywołania zwrotne jest znacznie zmniejszona lub zniesiona.

16

Zamiast czekać, jesteś lepiej wyłączyć za pomocą new test().Go().GetAwaiter().GetResult() ponieważ pozwoli uniknąć wyjątki są owinięte w AggregateExceptions, więc można po prostu otoczyć swoją metodę Go() z try catch (Exception ex) bloku, jak zwykle.

+0

IMO najlepsza odpowiedź, możesz nadal zwracać silne typy itp. –

4

Dopóki masz dostępu do obiektu wynikać ze zwróconego zadania, nie ma potrzeby korzystania GetAwaiter w ogóle (tylko w przypadku uzyskiwania dostępu wynik).

static async Task<String> sayHelloAsync(){ 

     await Task.Delay(1000); 
     return "hello world"; 

} 

static void main(string[] args){ 

     var data = sayHelloAsync(); 
     //implicitly waits for the result and makes synchronous call. 
     //no need for Console.ReadKey() 
     Console.Write(data.Result); 
     //synchronous call .. same as previous one 
     Console.Write(sayHelloAsync().GetAwaiter().GetResult()); 

} 

jeśli chcesz czekać na zadanie do zrobienia i zrobić dalszego przetworzenia:

sayHelloAsyn().GetAwaiter().OnCompleted(() => { 
    Console.Write("done"); 
}); 
Console.ReadLine(); 

Jeśli jesteś zainteresowany w uzyskaniu wyników z sayHelloAsync i zrobić dalszego przetwarzania na nim:

sayHelloAsync().ContinueWith(prev => { 
    //prev.Result should have "hello world" 
    Console.Write("done do further processing here .. here is the result from sayHelloAsync" + prev.Result); 
}); 
Console.ReadLine(); 

ostatnia prosta droga czekać na funkcję:

static void main(string[] args){ 
    sayHelloAsync().Wait(); 
    Console.Read(); 
} 

static async Task sayHelloAsync(){   
    await Task.Delay(1000); 
    Console.Write("hello world"); 

} 
7

Po wypuszczeniu C# 7.1, spowoduje to użycie asynchronicznych głównych metod i uniknięcie potrzeby obejścia w już opublikowanych odpowiedziach. Następujące podpisy zostały dodane:

public static Task Main(); 
public static Task<int> Main(); 
public static Task Main(string[] args); 
public static Task<int> Main(string[] args); 

To pozwala na pisanie kodu tak:.

static async Task Main(string[] args) 
{ 
    await DoSomethingAsync(); 
} 

static async Task DoSomethingAsync() 
{ 
    //... 
} 
3
class Program 
{ 
    static void Main(string[] args) 
    { 
     test t = new test(); 
     Task.Run(async() => await t.Go()); 
    } 
} 
Powiązane problemy