Co chcę zrealizować w moim programie jest następujący callstack/Workflow:Deadlock użyciu asynchronicznie i czekają
- dispatch()
- autoryzacji()
- HttpPost()
Mój pomysł był taki, że httpPost()
będzie asynchronizowany, podczas gdy pozostałe 2 metody pozostaną niezsynchronizowane. Jednak z jakiegoś powodu nie zadziałałoby to dla mnie, chyba że zrobię 2 + 3. async. Może nadal mam pewne nieporozumienia.
mojego rozeznania mogę albo a) używać await
-słowo kluczowe podczas wywoływania metody asynchronicznej (ten zawiesi metody i kontynuować po zakończeniu sposób asynchroniczny) lub b) ommit await
-słowo kluczowe i zamiast zadzwonić zadanie. Wynik metody asynchronicznej zwraca wartość, która będzie blokowana, dopóki wynik nie będzie dostępny.
Pokażę wam przykład robocza:
private int dispatch(string options)
{
int res = authorize(options).Result;
return res;
}
static async private Task<int> authorize(string options)
{
string values= getValuesFromOptions(options);
KeyValuePair<int, string> response = await httpPost(url, values);
return 0;
}
public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
{
var httpClient = new HttpClient(new HttpClientHandler());
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
int code = (int)response.StatusCode;
response.EnsureSuccessStatusCode();
string responseString = await response.Content.ReadAsStringAsync();
return new KeyValuePair<int, string>(code, responseString);
}
Pokażę wam przykład non -Praca:
private int dispatch(string options)
{
int res = authorize(options).Result;
return res;
}
static private int authorize(string options)
{
string values= getValuesFromOptions(options);
Task<KeyValuePair<int, string>> response = httpPost(url, values);
doSomethingWith(response.Result); // execution will hang here forever
return 0;
}
public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
{
var httpClient = new HttpClient(new HttpClientHandler());
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
int code = (int)response.StatusCode;
response.EnsureSuccessStatusCode();
string responseString = await response.Content.ReadAsStringAsync();
return new KeyValuePair<int, string>(code, responseString);
}
Próbowałem też mieć wszystko 3 metody niezsynchronizowane i zastępujące await
s w await
s w await
s z .Result
s, ale potem będzie wisiał na zawsze w linii HttpResponseMessage response = httpClient.PostAsync(url, new FormUrlEncodedContent(parameters)).Result;
Czy ktoś mógłby mnie oświecić i wyjaśnić, co mój błąd?
Aby sprawdzić, czy jest to poprawne wyjaśnienie, weź niedziałający kod i zmień każde "oczekuj X" na "czekać na X.ConfigureAwait (fałsz)". Jeśli wyjaśnienie jest poprawne, powinno teraz działać. Kolejna uwaga: masz kontekst synchronizacji, jeśli używasz ASP.Net lub aplikacji interfejsu użytkownika. Jeśli tak, porównaj ten sam kod w samodzielnym projekcie konsoli. – danarmak
@servy: To, czego nie dostaję, to jednak faktyczna różnica pomiędzy moim przykładem roboczym a niedziałającym przykładem. Rozumiem, że mówisz, że 'czekaj' ma harmonogram kontynuacji, podczas gdy' .Rekult' po prostu blokuje (czy tak?), Ale nie znaczyłoby to, że potrzebowałem niekończącego się łańcucha oczekującego na oczekiwanie, ponieważ bez 'wyczekiwania 'blokowałbym/zakleszczenie mój wątek? Mam na myśli pierwszy przykład robi * nie * blok w 'int res = authorize (options) .Result;', ale drugi przykład blokuje w 'doSomethingWith (response.Result);', dlaczego? – user826955