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);

David Dury
źródło
1
Przeczytaj także MSDN: msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx .
Patrick Hofman,
@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.

Sriram Sakthivel
źródło
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

Poważny
źródło
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.

Jeremy Lakeman
źródło
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";

        }))());
    }
Adel Mourad
źródło
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 ())

abhiroop mukherjee
źródło