CancellationToken: почему структура?

296
10 ноября 2017, 06:57

Почему CancellationToken реализован как структура?
Ведь структура является типом значения, как тогда реализован данный механизм?

static void Main(string[] args)
{
    CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
    CancellationToken token = cancelTokenSource.Token;
    Task task1 = new Task(() => Factorial(5, token));
    task1.Start();
    cancelTokenSource.Cancel();
}
static void Factorial(int x, CancellationToken token)
{
    int result = 1;
    for (int i = 1; i <= x; i++)
    {
        if (token.IsCancellationRequested)
        {
            Console.WriteLine("Операция прервана токеном");
            return;
        }
        result *= i;
        Console.WriteLine("Факториал числа {0} равен {1}", i, result);
        Thread.Sleep(5000);
    }
}

Ведь структура является типом значения и создается копия объекта при передачи параметра CancellationToken token

Answer 1

Почему CancellationToken реализован как структура?

Для борьбы за эффективность.

В большинстве случаев, да, CancellationToken вполне мог бы быть и классом, одна аллокация ничего не меняет, так как многопоточный код обычно некритичен к паре лишних мелких аллокаций.

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

(Например, если пользователь хочет в метод, который ожидает CancellationToken, передать CancellationToken.None, потому что ему нужна скорость и не нужна отмена.)

Так что разработчики решили облегчить нам, пользователям, жизнь, и сделали CancellationToken таки структурой.

По поводу реализации механизма: да, разработчики нарушили семантику, и CancellationToken ведёт себя как типичный класс, а не как типичная структура. Они реализовали это таким образом. В CancellationToken есть единственное поле private CancellationTokenSource m_source; (ссылка на исходники). В проверке на равенство сравнивается m_source, и при копировании m_source копируется тоже, так что копия токена ведёт себя как оригинал, и тем самым неотличима от него. В частности, если оригинал токена отменён, то его копия — тоже.

READ ALSO
WPF/MVVM объединить модели во ViewModel

WPF/MVVM объединить модели во ViewModel

Буду излагать суть проблемы максимально краткоИмеется 2 модели:

275
C#, MySql Connection must be valid and open

C#, MySql Connection must be valid and open

Вот дебильный быть может вопрос

246
C# MySql как конвертировать mysql таблицу в excel

C# MySql как конвертировать mysql таблицу в excel

Добрый вечер господа как конвертировать mysql таблицу в excel на C#Я установил эти ссылки(подключил пакеты):

312
Выполнить метод из стороннего класса

Выполнить метод из стороннего класса

Столкнулась с такой проблемой: Принимаю callback с сайта и обрабатываю его

234