class Program
{
static async Task Main(string[] args)
{
Console.WriteLine($"The main thread is {Thread.CurrentThread.ManagedThreadId}");
var cts = new CancellationTokenSource();
Person p = new Person { Name = "Apple" };
try
{
cts.CancelAfter(TimeSpan.FromSeconds(3));//limited to 3 seconds
DoSth(p).Wait(cts.Token);
}
catch
{
}
Console.WriteLine(cts.Token.IsCancellationRequested);
Thread.Sleep(3000);
Console.ReadLine();
}
static async Task DoSth(Person p)
{
await Task.Run(() =>
{
p.Name = "Cat";
Thread.Sleep(5000);
Console.WriteLine($"The async thread is {Thread.CurrentThread.ManagedThreadId}");
});
}
}
Как вы можете видеть код выше, я получил результат:
The main thread is 1
True
The async thread is 4
Кажется, что метод все еще работает после отмены? Можно ли прервать задание через какое-то время? Когда я пытаюсь использовать Thread.Abort(), я получаю предупреждение о том, что этот метод устарел.
Вещи, которые я нахожу здесь странными: использование Thread.Sleep
в async Task Main
вместо await Task.Delay
. Вызов DoSth(p).Wait(cts.Token);
вместо await DoSth(p)
или, возможно, await DoSth(p, cts.Token);
, если вы измените его, чтобы получить CancellationToken
. Пустой улов, который просто проглатывает любые исключения, тоже не очень хорош.
Если вы хотите прервать задачу через 3 секунды, вам нужно отправить токен в функцию. Если вы используете Task.Delay
и отправляете токен, который вызовет исключение при отмене и прервет задачу.
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine($"The main thread is {Thread.CurrentThread.ManagedThreadId}");
var cts = new CancellationTokenSource();
Person p = new Person { Name = "Apple" };
try
{
cts.CancelAfter(TimeSpan.FromSeconds(3));//limited to 3 seconds
await DoSth(p, cts.Token);
}
catch (Exception e)
{
Console.WriteLine(e.Message); //task was canceled
}
Console.WriteLine(cts.Token.IsCancellationRequested);
await Task.Delay(3000);
Console.ReadLine();
}
static async Task DoSth(Person p, CancellationToken ct)
{
p.Name = "Cat";
await Task.Delay(5000, ct); //Will throw on cancellation, so next row will not run if cancelled after 3s.
Console.WriteLine($"The async thread is {Thread.CurrentThread.ManagedThreadId}");
}
}
public class Person
{
public string Name { get; set; }
}
Вы отменяете задачу в ожидании, но не отменяете задачу. Мы видим это, потому что сама задача не имеет совместной отмены и не получает
CancellationToken
.