У меня есть форма 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();
}
}
Однако это кажется очень неэлегантным — прежде всего мне нужно выполнить Task.Run(ThingDoingTask), чтобы создать новый поток, который сам вызывает то, что я действительно хочу сделать с помощью Task.Wait()< /code>, чтобы передать ему токен отмены. Это связано с тем, что Task.Wait() блокируется, поэтому, если я просто позвоню из btnStart_Click(), я не смогу нажать кнопку «Отмена». (и хотя Task.Run() принимает токен, он не выдает исключение при отмене.) Затем мне нужно дважды проверить IsCancellationRequested после его завершения, потому что это не так. не знаю, было ли создано исключение.
Во-вторых, метод DoSomethingThatTakesALongTime() продолжает работу даже после того, как он создал исключение. Полагаю, я мог бы также проверить здесь IsCancellationRequested, но я думал, что смысл ThrowIfCancellationRequested() состоит в том, чтобы избежать перегрузки кода большим количеством проверок токена? И токен на самом деле недоступен в этом методе (просто он является частным свойством этого простого демонстрационного класса, но в сложных приложениях это будет не очень полезно)
Что правильный способ написать это простое приложение или использовать ThrowIfCancellationRequested ?
Подробнее здесь: https://stackoverflow.com/questions/791 ... nrequested
Мобильная версия