Aby odpowiedzieć na to 2nd część pierwsza, tak trzeba zaznaczyć zdarzenia dla przycisku async
, jeśli chcesz użyć słowa kluczowego await
w kodzie trzeba zadeklarować funkcję async
.
2ndly jeśli funkcja wykorzystuje async
bez posiadania await
wewnątrz niego kod nie będzie uruchamiane asynchronicznie, albo trzeba utworzyć zadanie i uruchomić synchroniczne metodę wewnątrz niego lub przepisać metodę być asynchroniczny.
jako metoda zadanie:
private async void button1_Click(object sender, EventArgs e)
{
txtLog.AppendText("Before Await");
//Note I changed from "Task<bool>" to "bool", await is like calling ".Result"
// on a task but not blocking the UI, so you store the type you are waiting for.
bool result = await Task.Run(() => login("","")); //You would still use your old login code before you tried to make it async, it requires no modifications.
txtLog.AppendText("After Await");
txtLog.AppendText("Result: " + result.ToString());
}
Przepisanie sposobu funkcję:
private async void button1_Click(object sender, EventArgs e)
{
txtLog.AppendText("Before Await");
//Note I changed from "Task<bool>" to "bool", await is like calling ".Result"
// on a task but not blocking the UI, so you store the type you are waiting for.
bool result = await login("","");
txtLog.AppendText("After Await");
txtLog.AppendText("Result: " + result.ToString());
}
private Task<bool> login(String username, String password)
{
var tcs = new TaskCompletionSource<bool>();
// Make the login request
var request = new RestSharp.RestRequest("/accounts/login/", RestSharp.Method.POST);
request.AddParameter("username", username);
request.AddParameter("password", password);
client.ExecuteAsync(request, (response, handle) =>
{
try
{
// Return loggin status
var dom = response.Content;
//dom["html"] did not have a .HasClass in my tests, so this code may need work.
tcs.TrySetResult(dom["html"].HasClass("logged-in"));
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}
W moim "metody przepisywania" co robie to używam ExecuteAsync
czarownica jest part of IRestClient. Ta funkcja wywołuje metodę wywołania zwrotnego po jej zakończeniu w metodzie wywołania zwrotnego, którą wywołuję tcs
's, aby otrzymać wynik, który chciałem.
Można rozszerzyć ten dodatkowo biorąc w CancellationToken
a jeśli znacznik jest podniesiona połączenia Abort()
na RestRequestAsyncHandle
, jednak jeśli to zrobimy musimy wnieść async
powrotem do funkcji i poczekać na wynik więc możemy oczyścić po rejestracji tokena anulowania.
private Task<bool> login(String username, String password)
{
return login(username, password, CancellationToken.None);
}
private async Task<bool> login(String username, String password, CancellationToken cancelToken)
{
var tcs = new TaskCompletionSource<bool>();
// Make the login request
var request = new RestSharp.RestRequest("/accounts/login/", RestSharp.Method.POST);
request.AddParameter("username", username);
request.AddParameter("password", password);
var asyncHandle = client.ExecuteAsync(request, (response, handle) =>
{
try
{
// Return loggin status
var dom = response.Content;
tcs.TrySetResult(dom["html"].HasClass("logged-in"));
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
});
//if the token is canceled it will call `asyncHandle.Abort()` for us.
using(cancelToken.Register(() =>
{
if(tcs.TrySetCanceled(cancelToken))
asyncHandle.Abort();
}))
{
return await tcs.Task;
}
}
Scott właśnie odpowiedział na dwa pytania w jednym dla mnie, bo ja po prostu patrząc w górę, jak korzystać ExecuteAsync i był już wiedzą jak z niego korzystać. Ponadto używałem CsQuery, który ma metodę "HasClass". –
Wprowadziłem kilka poprawek w wersji podlegającej anulowaniu, musisz powiadomić 'tcs', że zadanie zostało anulowane.Dodałem także obsługę tego zgłoszenia wszelkich wyjątków, które mogą być zgłaszane na wywołanie zwrotne. –
Ta odpowiedź jest dla mnie pomocna. Dziękuję Ci. –