2016-08-05 4 views
4

Мы все знаем методы, такие как Task.Run или Parallel.ForEach. Каждый из них создает задачи, которые выполняются в соответствии с параметрами в отдельном потоке или в потоке из пула потоков. Но где их стек? В какой-то куче поколения или для них есть особое место?Где находится стек задач, выделенный в C#?

Например, я могу создать 1000 задач, и где их стеки проживают? Будет ли их физический адрес перемещаться в какой-то момент, если я вызову GC.Collect()?

+2

Это довольно специфично в отношении конкретной реализации CLR, базовой ОС и даже архитектуры процессора. Например, Windows имеет определенную поддержку для распределения (и роста) стеков потоков в соответствии с тем, как работает управление памятью x86/x64. –

+0

Действительно. На языке C# очень мало требований, что все стеки существуют (на самом деле это просто распределение стека - в языке C# имеется только 44 экземпляра 'stack', а половина из них - это классы классов, называемые' Stack') –

ответ

3

Стек представляет собой исключительно неуправляемую деталь реализации. Процессору нужен стек, чтобы что-то сделать, он не может без проблем выполнять какой-либо код без него. Он сильно привязан к потоку, еще одна неуправляемая информация о обычных хостах CLR.

Он расположен в памяти, где ядро ​​ОС решило выделить его при создании потока, оно случайное. Преднамеренно случайным образом, чтобы вредоносное ПО было затруднено, стек представляет собой привлекательный способ превратить данные во вредоносный код. Не только случайное местоположение, но и точное смещение внутри сегмента стека, в котором начинается старт, является случайным.

Он не перемещается после его создания, GC не возится с ним. Он должен знать об этом, корни объектов могут храниться в стеке. Таким образом, надежные стековые транзакции - это жесткое требование .NET, а также основная причина того, что CLR всегда может создавать хорошую трассировку стека, когда программа умирает от необработанного исключения. Запуск из пространства стека является серьезной проблемой, процессор не может продолжать выполнять код. Достаточно серьезный, чтобы назвать веб-сайт программиста после этой проблемы.

2

Задачи, которые основаны на делегатах, выполненных по TaskScheduler, выполняются в любом стеке, используемом TaskScheduler. Планировщик по умолчанию использует потоки пула потоков. Это (в основном) обычные потоки .NET.

В частности, Task.Run создает такую ​​задачу на основе планировщика по умолчанию.

Задачи, основанные на TaskCompletionSource, не выполняют код и не нуждаются в стеке. Они завершаются на основе некоторых внешних условий, таких как завершение ввода-вывода или таймер.

.NET не имеет встроенной поддержки для кучи на основе кучи или «зеленых потоков». Обычно вы не найдете такой вещи в реальном коде.

Смежные вопросы