Я создал сервер, который выполняет некоторые задачи с блокирующей операцией, я использовал cancellationToken, чтобы остановить эту задачу с блокирующей операцией. Ниже приведен пример задачи для TcpConnection:
private List<CancellationTokenSource> cancellations = new List<CancellationTokenSource>();
:
:
private async Task ListenAsync()
{
try {
CancellationTokenSource cancellation = new CancellationTokenSource();
cancellations.Add(cancellation);
TcpClient client = await Task.Run(
() => listener.AcceptTcpClientAsync(),
cancellation.Token);
:
:
}
}
Когда мне нужно остановить сервер, я постараюсь отменить все токены отмены в списке, а затем уничтожить все задачи.
foreach (CancellationTokenSource cancellation in cancellations)
{
cancellation.Cancel();
}
Task.WhenAll(tasks).Wait(); // wait for task complete
: (desotry objects here)
:
К сожалению, Task.WhenAll (задачи) .Wait () никогда не возвращался. Кажется, что задачи не могут быть остановлены. Но если я добавлю некоторый отладочный код в Try Catch в Task и закомментирую Task.WhenAll (tasks) .Wait (), он запустит оператор catch после cancellation.Cancel (), и задача будет выполнена.
Кажется, что если Wait () запускается в том же потоке отмены. Cancel (), он не может освободить элемент управления для Задачи, даже если я добавил Thread.sleep () после Cancel. Мне нужно проверить Task.wait () в другом процессе (например, добавить таймер для запуска через несколько мс после отмены.) Или, если я не жду отмены задачи, и сбросить список задач (например, tasks = new List (); ). Эти запущенные задачи достигнут блока catch и также будут выполнены, но я не знаю, можно ли повторно использовать эти ресурсы после удаления всех ссылок на эти задачи до завершения задачи.
Я хотел бы знать, есть ли прямой способ ожидания завершения задачи с использованием CancellationToken. Так что я могу очистить все объекты безопасности.