Я пытаюсь использовать токены отмены, как описано в это часто задаваемые вопросы. Это была моя первоначальная мысль:
private async void OnLoginButtonClicked(object sender, EventArgs e)
{
if (this.cancelToken == null)
{
this.cancelToken = new CancellationTokenSource();
}
try
{
bool loginSuccess = await AsyncLoginTask(this.cancelToken.Token);
if (loginSuccess)
{
// Show main page
}
}
catch (OperationCanceledException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
finally
{
this.cancelToken = null;
}
}
private async Task<bool> AsyncLoginTask(CancellationToken cancellationToken = default(CancellationToken))
{
// Pass the token to HttpClient()
}
Сейчас я его адаптировал и вот результат:
private async void OnLoginButtonClicked(object sender, EventArgs e)
{
this.cancelToken?.Dispose();
this.cancelToken = new CancellationTokenSource();
try
{
var ui = TaskScheduler.FromCurrentSynchronizationContext();
var loginTask = Task.Factory.StartNew(async () =>
{
bool loginSuccess = await AsyncLoginTask(this.cancelToken.Token);
}, this.cancelToken.Token);
var displayResults = loginTask.ContinueWith(resultTask =>
{
// How do I know if the login was successful?
// Because AsyncLoginTask() returns bool.
System.Diagnostics.Debug.WriteLine("done");
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
ui);
var displayCancelledTasks = loginTask.ContinueWith(resultTask =>
{
System.Diagnostics.Debug.WriteLine("canceled");
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnCanceled, ui);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
Вопросы:
- Как я узнаю, что вход был успешным? Поскольку
AsyncLoginTask()
возвращаетbool
. - Как правильно создать и уничтожить токен, чтобы разрешить запуск и отмену операции несколько раз?
- Как обрабатывать задачу в задаче? «Готово» отображается в консоли, а задача (AsyncLoginTask) еще не завершена.
How do I know if the login was successful? Because AsyncLoginTask() returns bool
ну можно вернутьloginSuccess
в той задаче, что дастloginTask
результат. Но... мой вопрос заключается в том, почему вы хотите обернуть задачу входа в задачу? - person Stefan   schedule 30.05.2017AsyncLoginTask
) был построен таким образом (асинхронно/ожидание с возвратом true/false). Теперь я хочу, чтобы пользователь мог отменить операцию. В связанной статье это рекомендуемый способ работы с задачей иContinueWith
. Итак, я завершил свою задачу. Должен ли я остаться с ловлейOperationCanceledException
? - person testing   schedule 30.05.2017await
кажется мне более интуитивным. Вы можете справиться с этой отменой соответствующим образом. Можете ли вы объяснить свою настоящую цель и почему вы думаете, что этот рефакторинг поможет ее достичь? - person Stefan   schedule 30.05.2017Task.Factory.StartNew
и.ContinueWith
устарели и заменены шаблономasync await
- person Default   schedule 30.05.2017StartNew
иContinueWith
в некоторых случаях могут привести к неожиданным результатам. Иdone
пишется в консоли, потому чтоawait
во внутренней задаче завершается, пока вы не получите результат из http-запроса. - person VMAtm   schedule 30.05.2017CancellationTokenSource
и пробовал кое-что, не зная, правильно ли это. Потом нашел статью, которая привела ко второй версии. Кроме того, когда я должен пойматьTaskCanceledException
, когдаOperationCanceledException
? Исключение, которое я получил, было своего рода ограниченным (я действительно не мог отлаживать), но, похоже, это былоOperationCanceledException
. Я знаю, что внутренняя задача завершается, пока я не получу результат, но я не понимаю, почему. Поскольку я откажусь от второго подхода, этот вопрос сейчас менее актуален. - person testing   schedule 30.05.2017await
— она возвращается из первогоawait
, сохраняет контекст и освобождает поток. Вы должны пойматьOperationCanceledException
, это базовый класс, stackoverflow.com/a/13040503/213550 - person VMAtm   schedule 30.05.2017