Rozważmy tę bardzo prostą metodę asynchroniczną:
static async Task myMethodAsync()
{
await Task.Delay(500);
}
Kiedy kompiluję to za pomocą VS2013 (kompilator sprzed Roslyn), wygenerowana maszyna stanu jest strukturą.
private struct <myMethodAsync>d__0 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
Kiedy kompiluję go z VS2015 (Roslyn), wygenerowany kod wygląda tak:
private sealed class <myMethodAsync>d__1 : IAsyncStateMachine
{
...
void IAsyncStateMachine.MoveNext()
{
...
}
}
Jak widać Roslyn generuje klasę (a nie strukturę). Jeśli dobrze pamiętam, pierwsze implementacje async / await w starym kompilatorze (chyba CTP2012) również generowały klasy, a następnie ze względów wydajnościowych zostało zmienione na struct. (w niektórych przypadkach można całkowicie uniknąć boksowania i alokacji sterty…) (Zobacz to )
Czy ktoś wie, dlaczego zmieniono to ponownie w Roslyn? (Nie mam z tym problemu, wiem że ta zmiana jest przejrzysta i nie zmienia zachowania żadnego kodu, jestem po prostu ciekawy)
Edytować:
Odpowiedź od @Damien_The_Unbeliever (i kod źródłowy :)) imho wyjaśnia wszystko. Opisane zachowanie Roslyn dotyczy tylko kompilacji debugowania (i jest to potrzebne ze względu na ograniczenie środowiska CLR wspomniane w komentarzu). W wersji Release generuje również strukturę (ze wszystkimi tego korzyściami ...). Wydaje się więc, że jest to bardzo sprytne rozwiązanie obsługujące zarówno Edycję, jak i Kontynuuj oraz lepszą wydajność w produkcji. Ciekawe rzeczy, dziękujemy wszystkim, którzy wzięli udział!
async
metody prawie zawsze mają prawdziwy punkt asynchroniczny -await
który zapewnia kontrolę, która i tak wymagałaby zapakowania struktury. Uważam, że struktury zmniejszyłyby obciążenie pamięci tylko w przypadkuasync
metod, które działały synchronicznie.