async await return Task


131

Czy ktoś może wyjaśnić, co to oznacza dla metody synchronicznej? Jeśli spróbuję zmienić metodę na asyncto VS narzekają na to.

To działa:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

To nie działa:

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

Zasadniczo chciałbym wiedzieć, co to dokładnie oznacza: Task.FromResult<object>(null);



@LB hmm, to działa! Ale także jeśli po prostu return;działa ...!
— David Dury

2
Komunikat „nie działa” nie zapewnia dobrego opisu tego, co nie działa. Jaki jest komunikat o błędzie, który otrzymałeś?
— John Koerner,

@JohnKoerner Myślę, że to całkiem oczywiste, że kompilator może dać ten sam błąd, co przy próbie zwrócenia wartości w voidfunkcji.
— binki

Odpowiedzi:


236

asyncmetody różnią się od zwykłych metod. Cokolwiek zwracasz z asyncmetod, jest opakowane w plik Task.

Jeśli nie zwrócisz żadnej wartości (void), zostanie ona zapakowana Task, jeśli zwrócisz int, zostanie zapakowana Task<int>i tak dalej.

Jeśli twoja metoda asynchroniczna wymaga zwrócenia int, oznacz typ zwracania metody jako, Task<int>a zwrócisz zwykły, a intnie Task<int>. Kompilator będzie przekonwertować intdo Task<int>dla ciebie.

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

Tak samo, kiedy zwracasz Task<object>zwracany typ metody powinien byćTask<Task<object>>

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

Ponieważ Twoja metoda zwraca Task, nie powinna zwracać żadnej wartości. W przeciwnym razie nie będzie się kompilować.

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

Należy pamiętać, że metoda asynchroniczna bez awaitinstrukcji nie jest async.


1
U mnie ten typ zwrotu nie działa (chyba coś robię źle). Przykład statycznej async Task <string> DoStuff () {... = await SomeMethodAsync (); return "wartość ciągu"; } .. var x = DoStuff (); Ale ten x - jest typu „Task <string>”, a nie „string” ... Dlaczego tak jest?
— Prokurors,

3
@Prokurors Musisz DoStuff()też czekać . Na przykład:var x = await DoStuff();
— Sriram Sakthivel

5
Powinno byćreturn await Task.FromResult<object>(null);
— sandeep talabathula

@sandeeptalabathula, który jest równy zwrotowi null
— Sriram Sakthivel

2
Przykładem Task.WhenAnyjest @ProfK .
— Servy

55

Musisz użyć słowa kluczowego await, gdy używasz async, a typ zwracanej funkcji powinien być ogólny. Oto przykład ze zwracaną wartością:

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

Oto przykład bez zwracanej wartości:

public async Task MethodName()
{
    await Task.CompletedTask;
}

Przeczytaj to:

TPL: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx i Tasks: http://msdn.microsoft.com/en-us/library/system.threading .tasks (v = w porównaniu do 110) .aspx

Async: http://msdn.microsoft.com/en-us/library/hh156513.aspx Oczekiwanie: http://msdn.microsoft.com/en-us/library/hh156528.aspx


9
Możesz po prostu wrócić nullbezpośrednio, zamiast czekać na fikcyjne zadanie.
— Lee,

5
@Lee, ale jeśli to zrobisz, kompilator narzeka (daje ostrzeżenie), że asyncmetoda będzie wykonywana asynchronicznie z sugestią, aby użyć awaitsłowa kluczowego gdzieś w metodzie. Proponuję po prostu użyć return Task.FromResult((object)null);i usunąć asyncsłowo kluczowe, aby zmniejszyć hałas ostrzegawczy kompilatora.
— binki

Tak, próbowałem po prostu użyć returnw zadaniu, ale zadanie jest wykonywane, ponieważ returnnie zwracaTask
— Turner Bass

30

Dodanie słowa kluczowego async to tylko cukier składniowy, który upraszcza tworzenie maszyny stanów. Zasadniczo kompilator pobiera Twój kod;

public async Task MethodName()
{
     return null;
}

I zamienia to w;

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

Jeśli twój kod ma jakieś awaitsłowa kluczowe, kompilator musi wziąć twoją metodę i przekształcić ją w klasę reprezentującą maszynę stanu wymaganą do jej wykonania. Przy każdym awaitsłowie kluczowym stan zmiennych i stos zostaną zachowane w polach klasy, klasa doda się jako punkt zakończenia zadania, na które czekasz, a następnie wróci.

Po zakończeniu tego zadania Twoje zadanie zostanie ponownie wykonane. Tak więc na początku metody jest dodawany dodatkowy kod, aby przywrócić stan zmiennych i przejść do następnej części kodu.

Zobacz, co generuje async i await? na przykład krwawy.

Ten proces ma wiele wspólnego ze sposobem, w jaki kompilator obsługuje metody iteratora z instrukcjami yield.


2

To jest zadanie, które zwraca zadanie typu String (funkcja anonimowa C # lub innymi słowy jest używana delegacja „Func”)

    public static async Task<string> MyTask()
    {
        //C# anonymous AsyncTask
        return await Task.FromResult<string>(((Func<string>)(() =>
        {
            // your code here
            return  "string result here";

        }))());
    }

1
Wysyłając kod jako odpowiedź, podaj wyjaśnienie tego, co demonstrujesz. W takim przypadku dodajesz odpowiedź na stare pytanie, które ma już kilka odpowiedzi. Dodaj jedno lub dwa zdania opisujące, co demonstruje Twoja nowa odpowiedź, czego nie było już w innych odpowiedziach. Nie mówię, że coś jest nie tak z twoją odpowiedzią, po prostu proszę, abyś pomógł innym, wyrażając słowami to, co pokazujesz swoim kodem.
— ToolmakerSteve

0

Aby uzyskać prawidłowe odpowiedzi z metod asynchronicznych, należy ustawić await podczas wywoływania tych metod zadań. To będzie czekać na przekonwertowanie go z powrotem na zwracany typ wartości, a nie na typ zadania.

Np. Var content = await StringAsyncTask (

where public async Task < String > StringAsyncTask ())

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.