Po raz pierwszy używam async (i .Net 4.5) po raz pierwszy i natknąłem się na coś, co mnie zaskoczyło. Nie ma zbyt wielu informacji na temat klasy VoidTaskResult, którą mogę znaleźć w sieci, więc przyszedłem tutaj, aby sprawdzić, czy ktoś ma jakieś pomysły na temat tego, co się dzieje.Co to jest typ VoidTaskResult, ponieważ odnosi się do metod asynchronicznych?
Mój kod jest podobny do poniższego. Oczywiście jest to znacznie uproszczone. Podstawową ideą jest wywoływanie metod wtyczek, które są asynchroniczne. Jeśli zwrócą Zadanie, nie ma zwracanej wartości z połączenia asynchronicznego. Jeśli zwrócą Task <>, to jest. Nie wiemy z góry, jakiego rodzaju są, więc chodzi o to, aby przyjrzeć się typowi wyniku za pomocą odbicia (IsGenericType jest prawdziwe, jeśli typ to Type <>) i uzyskać wartość za pomocą typu dynamicznego.
W moim prawdziwym kodzie wywołuję metodę wtyczek poprzez odbicie. Nie sądzę, że powinno to wpłynąć na zachowanie, które widzę.
// plugin method
public Task yada()
{
// stuff
}
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
dynamic dynTask = task;
object result = dynTask.Result;
// do something with result
}
}
Działa to dobrze dla metody wtyczki pokazanej powyżej. IsGenericType ma wartość false (zgodnie z oczekiwaniami).
Jednak jeśli kiedykolwiek tak nieznacznie zmienić deklarację metody wtyczki, IsGenericType wraca teraz prawdziwymi i rzeczy przerwy:
public async Task yada()
{
// stuff
}
Gdy to zrobisz, następujące jest wyjątek od wyniku linia (Object = dynTask.Result;):
Jeśli kopać do obiektu zadania, to rzeczywiście wydaje się być typem. VoidTaskResult to prywatny typ w przestrzeni nazw wątków z prawie niczym.
Próbowałem zmiany mojego Telefoniczny kod:
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
object result = task.GetType().GetProperty("Result").GetMethod.Invoke(task, new object[] { });
// do something with result
}
}
Ten „powiedzie” w tym sensie, że nie rzuca, ale teraz wynik jest typu „VoidTaskResult”, których nie mogę sensownie zrób cokolwiek z.
Powinienem dodać, że ciężko mi jest nawet sformułować prawdziwe pytanie na to wszystko. Być może moje prawdziwe pytanie brzmi "What is VoidTaskResult?" Lub "Dlaczego ta dziwna rzecz ma miejsce, gdy dynamicznie wzywam metodę asynchroniczną?" a może nawet "Jak wywołać metody wtyczek, które są opcjonalnie asynchroniczne?" W każdym razie, umieszczam to tam w nadziei, że jeden z guru będzie mógł rzucić trochę światła.
Dlaczego zespół asynchroniczny wprowadził funkcję VoidTaskResult, zamiast tylko wprowadzać nietypowy obiekt TaskCompletionSource? – Puppy
@Puppy: Podejrzewam, że było o wiele mniej pracy. Napisanie nieinwazyjnego 'TaskCompletionSource' nie jest zbyt trudne, ale każdy publiczny API musi przejść przez garść innych" bramek ", zanim będzie mógł zostać zwolniony. Recenzje zabezpieczeń itp. –