Правильное использование ThrowIfCancellationRequestedC#

Место общения программистов C#
Ответить
Anonymous
 Правильное использование ThrowIfCancellationRequested

Сообщение Anonymous »

Я пытаюсь разобраться в работе CancellationToken.ThrowIfCancellationRequested(). Я считаю, что в некоторой степени это работает, но я просто хочу посмотреть, правильный ли это шаблон для его использования.
У меня есть форма Windows с двумя кнопками — одна для запуска задачи и один, чтобы отменить его. И мой код:

Код: Выделить всё

public partial class CancelForm : Form
{
private CancellationTokenSource _cancellationTokenSource;

public CancelForm()
{
InitializeComponent();
}

private async void btnStart_Click(object sender, EventArgs e)
{
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource.Token.ThrowIfCancellationRequested();

await Task.Run(ThingDoingTask);

if (_cancellationTokenSource.IsCancellationRequested)
{
MessageBox.Show("Task Cancelled.");
}
else
{
MessageBox.Show("Task completed!");
}
}

private void ThingDoingTask()
{
var task = DoSomethingThatTakesALongTime();

try
{
task.Wait(_cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("The task was cancelled");
}
}

private async Task DoSomethingThatTakesALongTime()
{
Console.WriteLine("Doing something that takes a long time");
for (int i = 0; i < 10; i++)
{
await Task.Delay(2000);
Console.WriteLine($"Count: {i}");
}

Console.WriteLine("Finished doing it");
}

private void btnCancel_Click(object sender, EventArgs e)
{
_cancellationTokenSource.Cancel();
}
}
Теперь это работает в том смысле, что когда я нажимаю btnCancel, оно перехватывает исключение, а затем появляется окно сообщения «Задача отменена».
Однако это кажется очень неэлегантным — прежде всего мне нужно выполнить Task.Run(ThingDoingTask), чтобы создать новый поток, который сам вызывает то, что я действительно хочу сделать с помощью Task.Wait()< /code>, чтобы передать ему токен отмены. Это связано с тем, что Task.Wait() блокируется, поэтому, если я просто позвоню из btnStart_Click(), я не смогу нажать кнопку «Отмена». (и хотя Task.Run() принимает токен, он не выдает исключение при отмене.) Затем мне нужно дважды проверить IsCancellationRequested после его завершения, потому что это не так. не знаю, было ли создано исключение.
Во-вторых, метод DoSomethingThatTakesALongTime() продолжает работу даже после того, как он создал исключение. Полагаю, я мог бы также проверить здесь IsCancellationRequested, но я думал, что смысл ThrowIfCancellationRequested() состоит в том, чтобы избежать перегрузки кода большим количеством проверок токена? И токен на самом деле недоступен в этом методе (просто он является частным свойством этого простого демонстрационного класса, но в сложных приложениях это будет не очень полезно)
Что правильный способ написать это простое приложение или использовать ThrowIfCancellationRequested ?

Подробнее здесь: https://stackoverflow.com/questions/791 ... nrequested
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»