Я играл вокруг с следующим фрагментом кода:Предоставляет ли ParameterizedThreadStart, чтобы экземпляр объекта не собирался собирать мусор?
class RunMeBaby
{
public void Start()
{
while (true)
{
Console.WriteLine("I'm " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
}
}
}
class Program
{
static void Main(string[] args)
{
RunMeBaby r = new RunMeBaby();
Thread t = new Thread(r.Start); // ParameterizedThreadStart delegate
r = null;
GC.Collect(GC.MaxGeneration);
t.Start();
r = new RunMeBaby();
t = new Thread(() => r.Start()); // ThreadStart delegate
t.Start();
//Thread.Sleep(1000);
r = null;
}
}
В то время как первая часть основным выполнена без сучка, то вторая часть терпит неудачу, когда я закомментировать вызов метод Thread.Sleep()
, Я получаю пустое исключение.
Мое понимание заключается в том, что выражение лямбда лениво оценивается, может случиться так, что новая нить не запускается достаточно быстро, а основная устанавливает r
на null
. Теперь я поставил эту «вторую часть» в статическом методе с r
с локальной областью, и проблема исчезла. Но я задаюсь вопросом, скрыта ли проблема планировщиком потоков в этом конкретном случае, может быть, на другой машине с другой рабочей нагрузкой, которая все еще может произойти. Или есть что-то о выражении лямбда, которое гарантирует, что хотя r
выпадает из области видимости, если он не был установлен в null
, он все равно упоминается.
И в конечном итоге я задаюсь вопросом, следует ли мне как можно больше использовать делегата ParameterizedThreadStart
или придерживаться лямбда, учитывая, что я соблюдаю определенные условия, чтобы сохранить их действительными.