Дело в том, что это может работать, но это не гарантировано для работы по спецификации. Люди обычно ищут код, который работает по правильным причинам, а не из-за случайной комбинации компилятора, среды выполнения и JIT, который может меняться в зависимости от версии платформы, физического ЦП, платформы и такие вещи, как x86 против x64.
Понимание модели памяти - очень очень сложная область, и я не претендую на звание эксперта; но люди, которые являются настоящими экспертами в этой области, уверяют меня, что поведение, которое вы наблюдаете, не гарантировано.
Вы можете опубликовать столько рабочих примеров, сколько захотите, но, к сожалению, это не сильно отличается от того, что «обычно работает». Это, конечно, не доказывает, что гарантированно для работы. Для опровержения потребовался бы только один контрпример, но проблема в том, чтобы найти его ...
Нет, у меня нет руки.
Обновление с повторяющимся контрпримером:
using System.Threading;
using System;
static class BackgroundTaskDemo
{
// make this volatile to fix it
private static bool stopping = false;
static void Main()
{
new Thread(DoWork).Start();
Thread.Sleep(5000);
stopping = true;
Console.WriteLine("Main exit");
Console.ReadLine();
}
static void DoWork()
{
int i = 0;
while (!stopping)
{
i++;
}
Console.WriteLine("DoWork exit " + i);
}
}
Выход:
Main exit
но все еще работает, при полной загрузке процессора; обратите внимание, что stopping
был установлен на true
к этому моменту. ReadLine
означает, что процесс не завершается. Похоже, что оптимизация зависит от размера кода внутри цикла (следовательно, i++
). Это работает только в режиме «релиз», очевидно. Добавьте volatile
и все работает нормально.