Как остановить выполнение потока в C#?

Каким образом можно изящно прервать долгие вычисления, которые выполняются в отдельном потоке, при действии пользователя, без нужды во вставке множества проверок на статус токена или булевых переменных? Как можно остановить выполнение функции неуправляемого кода, вызываемой из потока?
  • 31 декабря 2023 г. 2:57
Ответы на вопрос 2
Существует несколько способов остановить выполнение потока в C#. Один из способов - использовать CancellationToken. 

Пример использования CancellationToken для остановки выполнения потока:

```csharp
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // Создаем CancellationTokenSource
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken cancellationToken = cancellationTokenSource.Token;

        // Запускаем поток
        Thread thread = new Thread(() => LongRunningMethod(cancellationToken));
        thread.Start();

        // Ждем ввода пользователя и прерываем выполнение потока
        Console.WriteLine("Нажмите любую клавишу, чтобы остановить поток.");
        Console.ReadKey();

        cancellationTokenSource.Cancel();

        // Ждем завершения потока
        thread.Join();

        Console.WriteLine("Поток остановлен.");
    }

    static void LongRunningMethod(CancellationToken cancellationToken)
    {
        try
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // Долгие вычисления...

                Console.WriteLine("Вычисления...");
                Thread.Sleep(1000);
            }
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Метод остановлен.");
        }
        finally
        {
            // Очистка ресурсов
        }
    }
}
```

В данном примере используется CancellationTokenSource и CancellationToken. Мы передаем CancellationToken в метод LongRunningMethod и проверяем его статус в цикле. Если cancellationToken был отменен (метод Cancel вызывается из основного потока), то метод выбрасывает OperationCanceledException, который ловится в блоке catch и завершает выполнение метода.

Если нужно остановить выполнение функции неуправляемого кода, вызываемой из потока, то требуется использовать дополнительные средства контроля выполнения этого кода, например, использовать CancellationToken и проверять его статус в коде функции неуправляемого кода. Если функция неуправляемого кода не предоставляет механизмов для прерывания, то можно попробовать использовать метод Abort для прерывания выполнения потока, но это не рекомендуется из-за его небезопасности и потенциальных проблем с ресурсами и состоянием приложения.
Это вообще правильно?

Да, это правильно и это по сути единственный адекватный способ отмены долгоиграющих операций.
Когда-то давно у потоков был метод Abort, но его удалили, тк его использование очень часто приводило к неприятным багам.
Ну и пихать проверку cancellation token повсюду не обязательно.
Поток вызывает 1 функцию библиотечную неуправляемого кода, как ее прервать?

Безопасно - никак, если эта неуправляемая функция не предоставляет интерфейс для отмены.
Даже если бы и был способ (тот же Abort), то прерывание неуправляемого кода очень вероятно приведёт к утечке ресурсов (в лучшем случае не будет освобождена динамическая память)
Похожие вопросы