Trochę informacji ogólnych.
Uczę się stosu Web API i próbuję hermetyzować wszystkie dane w postaci obiektu „Result” z parametrami takimi jak Success i ErrorCodes.
Jednak różne metody dałyby różne wyniki i kody błędów, ale obiekt wyniku byłby generalnie tworzony w ten sam sposób.
Aby zaoszczędzić trochę czasu, a także dowiedzieć się więcej o możliwościach async / await w C #, próbuję owinąć wszystkie treści metod moich akcji interfejsu API w asynchronicznego delegata akcji, ale wpadłem w pewien problem ...
Biorąc pod uwagę następujące klasy:
public class Result
{
public bool Success { get; set; }
public List<int> ErrorCodes{ get; set; }
}
public async Task<Result> GetResultAsync()
{
return await DoSomethingAsync<Result>(result =>
{
// Do something here
result.Success = true;
if (SomethingIsTrue)
{
result.ErrorCodes.Add(404);
result.Success = false;
}
}
}
Chcę napisać metodę, która wykonuje akcję na obiekcie Result i zwraca ją. Zwykle byłoby to metodami synchronicznymi
public T DoSomethingAsync<T>(Action<T> resultBody) where T : Result, new()
{
T result = new T();
resultBody(result);
return result;
}
Ale jak przekształcić tę metodę w metodę asynchroniczną przy użyciu async / await?
Oto, czego próbowałem:
public async Task<T> DoSomethingAsync<T>(Action<T, Task> resultBody)
where T: Result, new()
{
// But I don't know what do do from here.
// What do I await?
}
c#
asynchronous
asp.net-web-api
async-await
c#-5.0
Albin Anke
źródło
źródło
new
-ing w góręT
, dlaczego metoda zapotrzebowanie być asynchroniczny? AFAIK w kodzie używającym asynchronicznych interfejsów API, wystarczy propagowaćasync
ness z innych używanych metod.Stream.ReadAsync()
w metodzie, ta metoda powinna sama być asynchroniczna i zwracaćTask<T>
gdzieT
jest to, co zwróciłeś, gdyby metoda była synchroniczna. Chodzi o to, że w ten sposób każdy obiekt wywołujący twoją metodę może następnie „asynchronicznie czekać” (nie wiem, jaki jest na to dobry termin) na zakończenie działania bazowegoStream.ReadAsync()
. Metaforą tego, której możesz użyć, jest to, że asynchronizacja jest „zaraźliwa” i rozprzestrzenia się z wbudowanych operacji wejścia / wyjścia niskiego poziomu na inny kod, którego wyniki zależą od wyników wspomnianych operacji we / wy.Odpowiedzi:
async
OdpowiednikiemAction<T>
jestFunc<T, Task>
, więc wierzę, że to jest to, czego szukasz:public async Task<T> DoSomethingAsync<T>(Func<T, Task> resultBody) where T : Result, new() { T result = new T(); await resultBody(result); return result; }
źródło
void
metody jestTask
metoda -returning; w ten sposób asynchroniczny odpowiednikAction
isFunc<Task>
i asynchroniczny odpowiednikAction<T>
isFunc<T, Task>
. Więcej informacji tutaj .Task
gdy nie ma wartości zwracanej. Jeśli używaasync
słowa kluczowego, to właściwaTask
instancja zostanie utworzona przez automat stanowy, a nie bezpośrednio przez funkcję.Więc uważam, że sposobem na wdrożenie tego jest:
public Task<T> DoSomethingAsync<T>(Action<T> resultBody) where T : Result, new() { return Task<T>.Factory.StartNew(() => { T result = new T(); resultBody(result); return result; }); }
źródło
Task.Run
(a nawet bardziejStartNew
) w ASP.NET.